In this script, simulate 5 different data sets. All will be 50 subjects, 50 taxa, with 0.90 connectance but then varying degrees of covariate strength. Going to hold two covariate strengths constant and then vary the sex differences

1. Load Library


library(tidyverse)
library(igraph)
library(NBZIMM)
library(SpiecEasi)
library(LIMON)
library(here)
library(lme4)
library(Matrix)
library(tscount)
library(patchwork)
library(MASS)
library(matrixcalc)
library(gridExtra)
library(devtools)
library(miaSim)
library(reshape2)

2. Simulate beta = 0.01


Simulate Counts
Simulate GLV for 50 individuals, 50 species, 10 timepoints, Connectance = 0.90, Sex Beta = 0.01

# Set seed
set.seed(12345)

# Step 1 Run GLV for n number of subject and timepoints
###############################################################################

# Generate interactions from uniform distribution
A_uniform <- randomA(
    n_species = 50,
    diagonal = -1.0,
    connectance = 0.90)

# Create an empty list to store the count tables for each subject
count_tables <- list()


# Loop through 50 subjects and generate count tables for each
for (i in 1:50) {
  # Set the seed for each subject
  set.seed(12345 + i)  
 # Generalized Lotka-Volterra (gLV)
  tse_glv <- simulateGLV(n_species = 50,
                       A = A_uniform,
                       t_start = 0, 
                       t_store = 10,
                       stochastic = FALSE,
                       norm = FALSE,
                       error_variance = 0.01)
  
  # Get the count table
  sim_data <- tse_glv@assays@data@listData[["counts"]]
  
  # Store the count table in the list
  count_tables[[i]] <- t(sim_data)
}

# Step 2 - Merge together
###############################################################################
# Combine all count tables into one data frame
combined_count_table <- do.call(rbind, count_tables)

# Rename the rownames based on the count table number
rownames(combined_count_table) <- paste0("Sbj", rep(1:50, each = nrow(count_tables[[1]])), "_Time", 1:10)

Create Fake Metadata
1. Sex (M or F, 50/50 Ratio) 2. Age - sample from between 18 and 45 3. BMI - sample between 18 and 35

Make Metadata and merge with the count data

meta_data <-  expand.grid(Time = 1:10,ID = 1:50)
rownames(meta_data) <- rownames(combined_count_table)
# Set seed
set.seed(12345)
meta_data$Sex <- rep(c(0, 1), each = 50)
# Set seed
set.seed(12345)
meta_data$Age <- rep(sample(18:45, 50, replace = TRUE), each = 10)
# Set seed
set.seed(12345)
meta_data$BMI <- rep(sample(18:35, 50, replace = TRUE), each = 10)

# Center the continuous variables
meta_data$Age <- meta_data$Age - mean(meta_data$Age)
meta_data$BMI <- meta_data$BMI - mean(meta_data$BMI)


# Df 2 is Metadata merged with Counts
########################################################
#Round off and increase
combined_count_table <- as.data.frame(combined_count_table + abs(min(combined_count_table)))
combined_count_table <- (combined_count_table)*10
meta_counts <- base::merge(meta_data, combined_count_table, by ="row.names", all = TRUE)
meta_counts <- column_to_rownames(meta_counts, "Row.names")

Add in biological covariates

# Set seed
set.seed(12345)
# Addin covariates
########################################################################################
# Set up new dataframe
Long_data_new <- meta_counts


# Loop running the LM to get new variables with error that has a range of values
# Taxa 21 - 30 will have Sex effect
for (i in 26:35) {
  error <- rnorm(nrow(Long_data_new), mean = 1, sd = 0.6)
  Long_data_new[, i] <- Long_data_new[, i] + 0.01 * Long_data_new$Sex + error
}

# round the counts to bring them back up to 0
########################################################################################

# Add the minimum value to bring everything up to at least 0
count_table1 <- Long_data_new[,6:55]


# scale to positive and make larger
count_table1 <- count_table1 + abs(min(count_table1))
count_table1 <- round(count_table1*10)

#change Long_data_new
Long_data_new[,6:55] <- count_table1

Now Add in 0s

# Set up new dataframe
predata_0 <- count_table1

# Add the 0s back in
########################################################################################


# Step 1: Calculate total counts for each column
total_counts <- colSums(predata_0)


# Step 2: Create probability gradient
gradient <- seq(0.5, 0.2, length.out = ncol(predata_0))

# Step 3: Make the probability gradient inverse to total counts (ie higher total value, lower proportion of 0s)
total_counts <- total_counts[order(total_counts)]
gradient <- gradient[order(-gradient)]

# Step 4 & 5: Generate random numbers and set counts to 0 based on probability gradient

for (i in seq_along(total_counts)) {
  prob <- gradient[i]
  # Calculate number of 0s to add based on probability
  num_zeros <- sum(runif(nrow(predata_0)) <= prob)
  # Randomly select rows to set to 0
  # Set seed
  set.seed(12345+i)
  rows_to_zero <- sample(nrow(predata_0), num_zeros)
  # Set counts to 0
  predata_0[rows_to_zero, i] <- 0
}

# merge with metadata for plotting
zero_data1 <- merge(meta_data, predata_0, by = 0)
zero_data1 <- column_to_rownames(zero_data1, "Row.names")
#round the counts
zero_data1[,6:55] <- round(zero_data1[,6:55])

Graphs to Check

# Individual Species Plots
########################################################
# Pivot to long data
count_long <- tidyr::pivot_longer(zero_data1, cols = starts_with("sp"), names_to = "Species")

# Plot the data
count_long %>%
  ggplot(aes(x = Time, y = value, colour = as.factor(ID),
             group = as.factor(ID), linetype = as.factor(ID))) +
  geom_line() + 
  geom_point() +
  geom_jitter() +
  ylab("Count") +
  labs(linetype = "ID", color = "ID") +
  facet_wrap(~ Species) +  # Create a panel for each species
  theme(legend.position = "none") +
  ggtitle("Time Series of N=50, 0s")



# Distribution of counts
########################################################
hist(as.matrix(zero_data1[,6:55]), breaks = 100, main = "Distribution of GLV Data", xlab = "Counts")


# Correlation matrix
cor_raw1 <- cor((zero_data1[,6:55]), method = "spearman")
heatmap(cor_raw1, Colv = NA, Rowv = NA, main = "Correlation of 0 inflated no covariates")

Save the Counts

write.csv(meta_counts, here("Data","GLV_SimData", "Dataset_5","GLV_0.01.csv"))
write.csv(Long_data_new, here("Data","GLV_SimData", "Dataset_5","GLV_Cov_0.01.csv"))
write.csv(zero_data1, here("Data","GLV_SimData", "Dataset_5","GLV_CovZero_0.01.csv"))

3. Simulate beta = 0.10


Simulate Counts
Simulate GLV for 50 individuals, 50 species, 10 timepoints, Connectance = 0.90, Sex Beta = 0.1

# Set seed
set.seed(12345)

# Step 1 Run GLV for n number of subject and timepoints
###############################################################################

# Generate interactions from uniform distribution
A_uniform <- randomA(
    n_species = 50,
    diagonal = -1.0,
    connectance = 0.90)

# Create an empty list to store the count tables for each subject
count_tables <- list()


# Loop through 50 subjects and generate count tables for each
for (i in 1:50) {
  # Set the seed for each subject
  set.seed(12345 + i)  
 # Generalized Lotka-Volterra (gLV)
  tse_glv <- simulateGLV(n_species = 50,
                       A = A_uniform,
                       t_start = 0, 
                       t_store = 10,
                       stochastic = FALSE,
                       norm = FALSE,
                       error_variance = 0.01)
  
  # Get the count table
  sim_data <- tse_glv@assays@data@listData[["counts"]]
  
  # Store the count table in the list
  count_tables[[i]] <- t(sim_data)
}

# Step 2 - Merge together
###############################################################################
# Combine all count tables into one data frame
combined_count_table <- do.call(rbind, count_tables)

# Rename the rownames based on the count table number
rownames(combined_count_table) <- paste0("Sbj", rep(1:50, each = nrow(count_tables[[1]])), "_Time", 1:10)

Create Fake Metadata
1. Sex (M or F, 50/50 Ratio) 2. Age - sample from between 18 and 45 3. BMI - sample between 18 and 35

Make Metadata and merge with the count data

# Df 1 is Metadata
########################################################
meta_data <-  expand.grid(Time = 1:10,ID = 1:50)
rownames(meta_data) <- rownames(combined_count_table)
# Set seed
set.seed(12345)
meta_data$Sex <- rep(c(0, 1), each = 50)
# Set seed
set.seed(12345)
meta_data$Age <- rep(sample(18:45, 50, replace = TRUE), each = 10)
# Set seed
set.seed(12345)
meta_data$BMI <- rep(sample(18:35, 50, replace = TRUE), each = 10)

# Center the continuous variables
meta_data$Age <- meta_data$Age - mean(meta_data$Age)
meta_data$BMI <- meta_data$BMI - mean(meta_data$BMI)


# Df 2 is Metadata merged with Counts
########################################################
#Round off and increase
combined_count_table <- as.data.frame(combined_count_table + abs(min(combined_count_table)))
combined_count_table <- (combined_count_table)*10
meta_counts <- base::merge(meta_data, combined_count_table, by ="row.names", all = TRUE)
meta_counts <- column_to_rownames(meta_counts, "Row.names")

Add in biological covariates

# Set seed
set.seed(12345)
# Addin covariates
########################################################################################
# Set up new dataframe
Long_data_new <- meta_counts


# Loop running the LM to get new variables with error that has a range of values
# Taxa 21 - 30 will have Sex effect
for (i in 26:35) {
  error <- rnorm(nrow(Long_data_new), mean = 1, sd = 0.6)
  Long_data_new[, i] <- Long_data_new[, i] + 0.1 * Long_data_new$Sex + error
}

# round the counts to bring them back up to 0
########################################################################################

# Add the minimum value to bring everything up to at least 0
count_table1 <- Long_data_new[,6:55]


# scale to positive and make larger
count_table1 <- count_table1 + abs(min(count_table1))
count_table1 <- round(count_table1*10)

#change Long_data_new
Long_data_new[,6:55] <- count_table1

Now Add in 0s

# Set up new dataframe
predata_0 <- count_table1

# Add the 0s back in
########################################################################################


# Step 1: Calculate total counts for each column
total_counts <- colSums(predata_0)


# Step 2: Create probability gradient
gradient <- seq(0.5, 0.2, length.out = ncol(predata_0))

# Step 3: Make the probability gradient inverse to total counts (ie higher total value, lower proportion of 0s)
total_counts <- total_counts[order(total_counts)]
gradient <- gradient[order(-gradient)]

# Step 4 & 5: Generate random numbers and set counts to 0 based on probability gradient

for (i in seq_along(total_counts)) {
  prob <- gradient[i]
  # Calculate number of 0s to add based on probability
  num_zeros <- sum(runif(nrow(predata_0)) <= prob)
  # Randomly select rows to set to 0
  # Set the seed for each subject
  set.seed(12345 + i)  
  rows_to_zero <- sample(nrow(predata_0), num_zeros)
  # Set counts to 0
  predata_0[rows_to_zero, i] <- 0
}

# merge with metadata for plotting
zero_data1 <- merge(meta_data, predata_0, by = 0)
zero_data1 <- column_to_rownames(zero_data1, "Row.names")
#round the counts
zero_data1[,6:55] <- round(zero_data1[,6:55])

Graphs to Check

# Individual Species Plots
########################################################
# Pivot to long data
count_long <- tidyr::pivot_longer(zero_data1, cols = starts_with("sp"), names_to = "Species")

# Plot the data
count_long %>%
  ggplot(aes(x = Time, y = value, colour = as.factor(ID),
             group = as.factor(ID), linetype = as.factor(ID))) +
  geom_line() + 
  geom_point() +
  geom_jitter() +
  ylab("Count") +
  labs(linetype = "ID", color = "ID") +
  facet_wrap(~ Species) +  # Create a panel for each species
  theme(legend.position = "none") +
  ggtitle("Time Series of N=50, 0s")



# Distribution of counts
########################################################
hist(as.matrix(zero_data1[,6:55]), breaks = 100, main = "Distribution of GLV Data", xlab = "Counts")


# Correlation matrix
cor_raw1 <- cor((zero_data1[,6:55]), method = "spearman")
heatmap(cor_raw1, Colv = NA, Rowv = NA, main = "Correlation of 0 inflated no covariates")

Save the Counts

write.csv(meta_counts, here("Data","GLV_SimData", "Dataset_5","GLV_0.10.csv"))
write.csv(Long_data_new, here("Data","GLV_SimData", "Dataset_5","GLV_Cov_0.10.csv"))
write.csv(zero_data1, here("Data","GLV_SimData", "Dataset_5","GLV_CovZero_0.10.csv"))

4. Simulate beta = 1.0


Simulate Counts
Simulate GLV for 50 individuals, 50 species, 10 timepoints, Connectance = 0.90, Sex Beta = 1.0

# Set seed
set.seed(12345)

# Step 1 Run GLV for n number of subject and timepoints
###############################################################################

# Generate interactions from uniform distribution
A_uniform <- randomA(
    n_species = 50,
    diagonal = -1.0,
    connectance = 0.90)

# Create an empty list to store the count tables for each subject
count_tables <- list()


# Loop through 50 subjects and generate count tables for each
for (i in 1:50) {
  # Set the seed for each subject
  set.seed(12345 + i)  
 # Generalized Lotka-Volterra (gLV)
  tse_glv <- simulateGLV(n_species = 50,
                       A = A_uniform,
                       t_start = 0, 
                       t_store = 10,
                       stochastic = FALSE,
                       norm = FALSE,
                       error_variance = 0.01)
  
  # Get the count table
  sim_data <- tse_glv@assays@data@listData[["counts"]]
  
  # Store the count table in the list
  count_tables[[i]] <- t(sim_data)
}

# Step 2 - Merge together
###############################################################################
# Combine all count tables into one data frame
combined_count_table <- do.call(rbind, count_tables)

# Rename the rownames based on the count table number
rownames(combined_count_table) <- paste0("Sbj", rep(1:50, each = nrow(count_tables[[1]])), "_Time", 1:10)

Create Fake Metadata
1. Sex (M or F, 50/50 Ratio) 2. Age - sample from between 18 and 45 3. BMI - sample between 18 and 35

Make Metadata and merge with the count data

# Df 1 is Metadata
########################################################
meta_data <-  expand.grid(Time = 1:10,ID = 1:50)
rownames(meta_data) <- rownames(combined_count_table)
# Set seed
set.seed(12345)
meta_data$Sex <- rep(c(0, 1), each = 50)
# Set seed
set.seed(12345)
meta_data$Age <- rep(sample(18:45, 50, replace = TRUE), each = 10)
# Set seed
set.seed(12345)
meta_data$BMI <- rep(sample(18:35, 50, replace = TRUE), each = 10)

# Center the continuous variables
meta_data$Age <- meta_data$Age - mean(meta_data$Age)
meta_data$BMI <- meta_data$BMI - mean(meta_data$BMI)


# Df 2 is Metadata merged with Counts
########################################################
#Round off and increase
combined_count_table <- as.data.frame(combined_count_table + abs(min(combined_count_table)))
combined_count_table <- (combined_count_table)*10
meta_counts <- base::merge(meta_data, combined_count_table, by ="row.names", all = TRUE)
meta_counts <- column_to_rownames(meta_counts, "Row.names")

Add in biological covariates

# Set seed
set.seed(12345)
# Addin covariates
########################################################################################
# Set up new dataframe
Long_data_new <- meta_counts


# Loop running the LM to get new variables with error that has a range of values
# Taxa 21 - 30 will have Sex effect
for (i in 26:35) {
  error <- rnorm(nrow(Long_data_new), mean = 1, sd = 0.6)
  Long_data_new[, i] <- Long_data_new[, i] + 1.0 * Long_data_new$Sex + error
}

# round the counts to bring them back up to 0
########################################################################################

# Add the minimum value to bring everything up to at least 0
count_table1 <- Long_data_new[,6:55]


# scale to positive and make larger
count_table1 <- count_table1 + abs(min(count_table1))
count_table1 <- round(count_table1*10)

#change Long_data_new
Long_data_new[,6:55] <- count_table1

Now Add in 0s

# Set up new dataframe
predata_0 <- count_table1

# Add the 0s back in
########################################################################################


# Step 1: Calculate total counts for each column
total_counts <- colSums(predata_0)


# Step 2: Create probability gradient
gradient <- seq(0.5, 0.2, length.out = ncol(predata_0))

# Step 3: Make the probability gradient inverse to total counts (ie higher total value, lower proportion of 0s)
total_counts <- total_counts[order(total_counts)]
gradient <- gradient[order(-gradient)]

# Step 4 & 5: Generate random numbers and set counts to 0 based on probability gradient

for (i in seq_along(total_counts)) {
  prob <- gradient[i]
  # Calculate number of 0s to add based on probability
  num_zeros <- sum(runif(nrow(predata_0)) <= prob)
  # Randomly select rows to set to 0
  # Set the seed for each subject
  set.seed(12345 + i)  
  rows_to_zero <- sample(nrow(predata_0), num_zeros)
  # Set counts to 0
  predata_0[rows_to_zero, i] <- 0
}

# merge with metadata for plotting
zero_data1 <- merge(meta_data, predata_0, by = 0)
zero_data1 <- column_to_rownames(zero_data1, "Row.names")
#round the counts
zero_data1[,6:55] <- round(zero_data1[,6:55])

Graphs to Check

# Individual Species Plots
########################################################
# Pivot to long data
count_long <- tidyr::pivot_longer(zero_data1, cols = starts_with("sp"), names_to = "Species")

# Plot the data
count_long %>%
  ggplot(aes(x = Time, y = value, colour = as.factor(ID),
             group = as.factor(ID), linetype = as.factor(ID))) +
  geom_line() + 
  geom_point() +
  geom_jitter() +
  ylab("Count") +
  labs(linetype = "ID", color = "ID") +
  facet_wrap(~ Species) +  # Create a panel for each species
  theme(legend.position = "none") +
  ggtitle("Time Series of N=50, 0s")



# Distribution of counts
########################################################
hist(as.matrix(zero_data1[,6:55]), breaks = 100, main = "Distribution of GLV Data", xlab = "Counts")


# Correlation matrix
cor_raw1 <- cor((zero_data1[,6:55]), method = "spearman")
heatmap(cor_raw1, Colv = NA, Rowv = NA, main = "Correlation of 0 inflated no covariates")

Save the Counts

write.csv(meta_counts, here("Data","GLV_SimData", "Dataset_5","GLV_1.0.csv"))
write.csv(Long_data_new, here("Data","GLV_SimData", "Dataset_5","GLV_Cov_1.0.csv"))
write.csv(zero_data1, here("Data","GLV_SimData", "Dataset_5","GLV_CovZero_1.0.csv"))

5. Simulate beta = 8.0


Simulate Counts
Simulate GLV for 50 individuals, 50 species, 10 timepoints, Connectance = 0.90, Sex Beta = 8.0

# Set seed
set.seed(12345)

# Step 1 Run GLV for n number of subject and timepoints
###############################################################################

# Generate interactions from uniform distribution
A_uniform <- randomA(
    n_species = 50,
    diagonal = -1.0,
    connectance = 0.90)

# Create an empty list to store the count tables for each subject
count_tables <- list()


# Loop through 50 subjects and generate count tables for each
for (i in 1:50) {
  # Set the seed for each subject
  set.seed(12345 + i)  
 # Generalized Lotka-Volterra (gLV)
  tse_glv <- simulateGLV(n_species = 50,
                       A = A_uniform,
                       t_start = 0, 
                       t_store = 10,
                       stochastic = FALSE,
                       norm = FALSE,
                       error_variance = 0.01)
  
  # Get the count table
  sim_data <- tse_glv@assays@data@listData[["counts"]]
  
  # Store the count table in the list
  count_tables[[i]] <- t(sim_data)
}

# Step 2 - Merge together
###############################################################################
# Combine all count tables into one data frame
combined_count_table <- do.call(rbind, count_tables)

# Rename the rownames based on the count table number
rownames(combined_count_table) <- paste0("Sbj", rep(1:50, each = nrow(count_tables[[1]])), "_Time", 1:10)

Create Fake Metadata
1. Sex (M or F, 50/50 Ratio) 2. Age - sample from between 18 and 45 3. BMI - sample between 18 and 35

Make Metadata and merge with the count data

# Df 1 is Metadata
########################################################
meta_data <-  expand.grid(Time = 1:10,ID = 1:50)
rownames(meta_data) <- rownames(combined_count_table)
# Set seed
set.seed(12345)
meta_data$Sex <- rep(c(0, 1), each = 50)
# Set seed
set.seed(12345)
meta_data$Age <- rep(sample(18:45, 50, replace = TRUE), each = 10)
# Set seed
set.seed(12345)
meta_data$BMI <- rep(sample(18:35, 50, replace = TRUE), each = 10)

# Center the continuous variables
meta_data$Age <- meta_data$Age - mean(meta_data$Age)
meta_data$BMI <- meta_data$BMI - mean(meta_data$BMI)


# Df 2 is Metadata merged with Counts
########################################################
#Round off and increase
combined_count_table <- as.data.frame(combined_count_table + abs(min(combined_count_table)))
combined_count_table <- (combined_count_table)*10
meta_counts <- base::merge(meta_data, combined_count_table, by ="row.names", all = TRUE)
meta_counts <- column_to_rownames(meta_counts, "Row.names")

Add in biological covariates

# Set seed
set.seed(12345)
# Addin covariates
########################################################################################
# Set up new dataframe
Long_data_new <- meta_counts


# Loop running the LM to get new variables with error that has a range of values

# Taxa 21 - 30 will have Sex effect
for (i in 26:35) {
  error <- rnorm(nrow(Long_data_new), mean = 1, sd = 0.6)
  Long_data_new[, i] <- Long_data_new[, i] + 8.0 * Long_data_new$Sex + error
}


# round the counts to bring them back up to 0
########################################################################################

# Add the minimum value to bring everything up to at least 0
count_table1 <- Long_data_new[,6:55]


# scale to positive and make larger
count_table1 <- count_table1 + abs(min(count_table1))
count_table1 <- round(count_table1*10)

#change Long_data_new
Long_data_new[,6:55] <- count_table1

Now Add in 0s

# Set up new dataframe
predata_0 <- count_table1

# Add the 0s back in
########################################################################################


# Step 1: Calculate total counts for each column
total_counts <- colSums(predata_0)


# Step 2: Create probability gradient
gradient <- seq(0.5, 0.2, length.out = ncol(predata_0))

# Step 3: Make the probability gradient inverse to total counts (ie higher total value, lower proportion of 0s)
total_counts <- total_counts[order(total_counts)]
gradient <- gradient[order(-gradient)]

# Step 4 & 5: Generate random numbers and set counts to 0 based on probability gradient

for (i in seq_along(total_counts)) {
  prob <- gradient[i]
  # Calculate number of 0s to add based on probability
  num_zeros <- sum(runif(nrow(predata_0)) <= prob)
  # Randomly select rows to set to 0
  # Set the seed for each subject
  set.seed(12345 + i)  
  rows_to_zero <- sample(nrow(predata_0), num_zeros)
  # Set counts to 0
  predata_0[rows_to_zero, i] <- 0
}

# merge with metadata for plotting
zero_data1 <- merge(meta_data, predata_0, by = 0)
zero_data1 <- column_to_rownames(zero_data1, "Row.names")
#round the counts
zero_data1[,6:55] <- round(zero_data1[,6:55])

Graphs to Check

# Individual Species Plots
########################################################
# Pivot to long data
count_long <- tidyr::pivot_longer(zero_data1, cols = starts_with("sp"), names_to = "Species")

# Plot the data
count_long %>%
  ggplot(aes(x = Time, y = value, colour = as.factor(ID),
             group = as.factor(ID), linetype = as.factor(ID))) +
  geom_line() + 
  geom_point() +
  geom_jitter() +
  ylab("Count") +
  labs(linetype = "ID", color = "ID") +
  facet_wrap(~ Species) +  # Create a panel for each species
  theme(legend.position = "none") +
  ggtitle("Time Series of N=50, 0s")



# Distribution of counts
########################################################
hist(as.matrix(zero_data1[,6:55]), breaks = 100, main = "Distribution of GLV Data", xlab = "Counts")


# Correlation matrix
cor_raw1 <- cor((zero_data1[,6:55]), method = "spearman")
heatmap(cor_raw1, Colv = NA, Rowv = NA, main = "Correlation of 0 inflated no covariates")

Save the Counts

write.csv(meta_counts, here("Data","GLV_SimData", "Dataset_5","GLV_8.0.csv"))
write.csv(Long_data_new, here("Data","GLV_SimData", "Dataset_5","GLV_Cov_8.0.csv"))
write.csv(zero_data1, here("Data","GLV_SimData", "Dataset_5","GLV_CovZero_8.0.csv"))

6. Simulate beta = 15.0


Simulate Counts
Simulate GLV for 50 individuals, 50 species, 10 timepoints, Connectance = 0.90, Sex Beta = 15.0

# Set seed
set.seed(12345)

# Step 1 Run GLV for n number of subject and timepoints
###############################################################################

# Generate interactions from uniform distribution
A_uniform <- randomA(
    n_species = 50,
    diagonal = -1.0,
    connectance = 0.90)

# Create an empty list to store the count tables for each subject
count_tables <- list()


# Loop through 50 subjects and generate count tables for each
for (i in 1:50) {
  # Set the seed for each subject
  set.seed(12345 + i)  
 # Generalized Lotka-Volterra (gLV)
  tse_glv <- simulateGLV(n_species = 50,
                       A = A_uniform,
                       t_start = 0, 
                       t_store = 10,
                       stochastic = FALSE,
                       norm = FALSE,
                       error_variance = 0.01)
  
  # Get the count table
  sim_data <- tse_glv@assays@data@listData[["counts"]]
  
  # Store the count table in the list
  count_tables[[i]] <- t(sim_data)
}

# Step 2 - Merge together
###############################################################################
# Combine all count tables into one data frame
combined_count_table <- do.call(rbind, count_tables)

# Rename the rownames based on the count table number
rownames(combined_count_table) <- paste0("Sbj", rep(1:50, each = nrow(count_tables[[1]])), "_Time", 1:10)

Create Fake Metadata
1. Sex (M or F, 50/50 Ratio) 2. Age - sample from between 18 and 45 3. BMI - sample between 18 and 35

Make Metadata and merge with the count data

# Df 1 is Metadata
########################################################
meta_data <-  expand.grid(Time = 1:10,ID = 1:50)
rownames(meta_data) <- rownames(combined_count_table)
# Set seed
set.seed(12345)
meta_data$Sex <- rep(c(0, 1), each = 50)
# Set seed
set.seed(12345)
meta_data$Age <- rep(sample(18:45, 50, replace = TRUE), each = 10)
# Set seed
set.seed(12345)
meta_data$BMI <- rep(sample(18:35, 50, replace = TRUE), each = 10)

# Center the continuous variables
meta_data$Age <- meta_data$Age - mean(meta_data$Age)
meta_data$BMI <- meta_data$BMI - mean(meta_data$BMI)


# Df 2 is Metadata merged with Counts
########################################################
#Round off and increase
combined_count_table <- as.data.frame(combined_count_table + abs(min(combined_count_table)))
combined_count_table <- (combined_count_table)*10
meta_counts <- base::merge(meta_data, combined_count_table, by ="row.names", all = TRUE)
meta_counts <- column_to_rownames(meta_counts, "Row.names")

Add in biological covariates

# Set seed
set.seed(12345)
# Addin covariates
########################################################################################
# Set up new dataframe
Long_data_new <- meta_counts


# Loop running the LM to get new variables with error that has a range of values
# Taxa 21 - 30 will have Sex effect
for (i in 26:35) {
  error <- rnorm(nrow(Long_data_new), mean = 1, sd = 0.6)
  Long_data_new[, i] <- Long_data_new[, i] + 15 * Long_data_new$Sex + error
}

# round the counts to bring them back up to 0
########################################################################################

# Add the minimum value to bring everything up to at least 0
count_table1 <- Long_data_new[,6:55]


# scale to positive and make larger
count_table1 <- count_table1 + abs(min(count_table1))
count_table1 <- round(count_table1*10)

#change Long_data_new
Long_data_new[,6:55] <- count_table1

Now Add in 0s

# Set up new dataframe
predata_0 <- count_table1

# Add the 0s back in
########################################################################################


# Step 1: Calculate total counts for each column
total_counts <- colSums(predata_0)


# Step 2: Create probability gradient
gradient <- seq(0.5, 0.2, length.out = ncol(predata_0))

# Step 3: Make the probability gradient inverse to total counts (ie higher total value, lower proportion of 0s)
total_counts <- total_counts[order(total_counts)]
gradient <- gradient[order(-gradient)]

# Step 4 & 5: Generate random numbers and set counts to 0 based on probability gradient

for (i in seq_along(total_counts)) {
  prob <- gradient[i]
  # Calculate number of 0s to add based on probability
  num_zeros <- sum(runif(nrow(predata_0)) <= prob)
  # Randomly select rows to set to 0
  # Set the seed for each subject
  set.seed(12345 + i)  
  rows_to_zero <- sample(nrow(predata_0), num_zeros)
  # Set counts to 0
  predata_0[rows_to_zero, i] <- 0
}

# merge with metadata for plotting
zero_data1 <- merge(meta_data, predata_0, by = 0)
zero_data1 <- column_to_rownames(zero_data1, "Row.names")
#round the counts
zero_data1[,6:55] <- round(zero_data1[,6:55])

Graphs to Check

# Individual Species Plots
########################################################
# Pivot to long data
count_long <- tidyr::pivot_longer(zero_data1, cols = starts_with("sp"), names_to = "Species")

# Plot the data
count_long %>%
  ggplot(aes(x = Time, y = value, colour = as.factor(ID),
             group = as.factor(ID), linetype = as.factor(ID))) +
  geom_line() + 
  geom_point() +
  geom_jitter() +
  ylab("Count") +
  labs(linetype = "ID", color = "ID") +
  facet_wrap(~ Species) +  # Create a panel for each species
  theme(legend.position = "none") +
  ggtitle("Time Series of N=50, 0s")



# Distribution of counts
########################################################
hist(as.matrix(zero_data1[,6:55]), breaks = 100, main = "Distribution of GLV Data", xlab = "Counts")


# Correlation matrix
cor_raw1 <- cor((zero_data1[,6:55]), method = "spearman")
heatmap(cor_raw1, Colv = NA, Rowv = NA, main = "Correlation of 0 inflated no covariates")

Save the Counts

write.csv(meta_counts, here("Data","GLV_SimData", "Dataset_5","GLV_15.0.csv"))
write.csv(Long_data_new, here("Data","GLV_SimData", "Dataset_5","GLV_Cov_15.0.csv"))
write.csv(zero_data1, here("Data","GLV_SimData", "Dataset_5","GLV_CovZero_15.0.csv"))
LS0tCnRpdGxlOiAiRGF0YSBTaW11bGF0aW9uIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpJbiB0aGlzIHNjcmlwdCwgc2ltdWxhdGUgNSBkaWZmZXJlbnQgZGF0YSBzZXRzLiBBbGwgd2lsbCBiZSA1MCBzdWJqZWN0cywgNTAgdGF4YSwgd2l0aCAwLjkwIGNvbm5lY3RhbmNlIGJ1dCB0aGVuIHZhcnlpbmcgZGVncmVlcyBvZiBjb3ZhcmlhdGUgc3RyZW5ndGguIEdvaW5nIHRvIGhvbGQgdHdvIGNvdmFyaWF0ZSBzdHJlbmd0aHMgY29uc3RhbnQgYW5kIHRoZW4gdmFyeSB0aGUgc2V4IGRpZmZlcmVuY2VzCgojIDEuIExvYWQgTGlicmFyeQoqKiogCgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGlncmFwaCkKbGlicmFyeShOQlpJTU0pCmxpYnJhcnkoU3BpZWNFYXNpKQpsaWJyYXJ5KExJTU9OKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkobG1lNCkKbGlicmFyeShNYXRyaXgpCmxpYnJhcnkodHNjb3VudCkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoTUFTUykKbGlicmFyeShtYXRyaXhjYWxjKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShkZXZ0b29scykKbGlicmFyeShtaWFTaW0pCmxpYnJhcnkocmVzaGFwZTIpCmBgYAoKCgojIDIuIFNpbXVsYXRlIGJldGEgPSAwLjAxCioqKiAKCl9fU2ltdWxhdGUgQ291bnRzX18gIApTaW11bGF0ZSBHTFYgZm9yIDUwIGluZGl2aWR1YWxzLCA1MCBzcGVjaWVzLCAxMCB0aW1lcG9pbnRzLCBDb25uZWN0YW5jZSA9IDAuOTAsIFNleCBCZXRhID0gMC4wMQpgYGB7cn0KIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKCiMgU3RlcCAxIFJ1biBHTFYgZm9yIG4gbnVtYmVyIG9mIHN1YmplY3QgYW5kIHRpbWVwb2ludHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBHZW5lcmF0ZSBpbnRlcmFjdGlvbnMgZnJvbSB1bmlmb3JtIGRpc3RyaWJ1dGlvbgpBX3VuaWZvcm0gPC0gcmFuZG9tQSgKICAgIG5fc3BlY2llcyA9IDUwLAogICAgZGlhZ29uYWwgPSAtMS4wLAogICAgY29ubmVjdGFuY2UgPSAwLjkwKQoKIyBDcmVhdGUgYW4gZW1wdHkgbGlzdCB0byBzdG9yZSB0aGUgY291bnQgdGFibGVzIGZvciBlYWNoIHN1YmplY3QKY291bnRfdGFibGVzIDwtIGxpc3QoKQoKCiMgTG9vcCB0aHJvdWdoIDUwIHN1YmplY3RzIGFuZCBnZW5lcmF0ZSBjb3VudCB0YWJsZXMgZm9yIGVhY2gKZm9yIChpIGluIDE6NTApIHsKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAjIEdlbmVyYWxpemVkIExvdGthLVZvbHRlcnJhIChnTFYpCiAgdHNlX2dsdiA8LSBzaW11bGF0ZUdMVihuX3NwZWNpZXMgPSA1MCwKICAgICAgICAgICAgICAgICAgICAgICBBID0gQV91bmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgIHRfc3RhcnQgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICB0X3N0b3JlID0gMTAsCiAgICAgICAgICAgICAgICAgICAgICAgc3RvY2hhc3RpYyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIG5vcm0gPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl92YXJpYW5jZSA9IDAuMDEpCiAgCiAgIyBHZXQgdGhlIGNvdW50IHRhYmxlCiAgc2ltX2RhdGEgPC0gdHNlX2dsdkBhc3NheXNAZGF0YUBsaXN0RGF0YVtbImNvdW50cyJdXQogIAogICMgU3RvcmUgdGhlIGNvdW50IHRhYmxlIGluIHRoZSBsaXN0CiAgY291bnRfdGFibGVzW1tpXV0gPC0gdChzaW1fZGF0YSkKfQoKIyBTdGVwIDIgLSBNZXJnZSB0b2dldGhlcgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgQ29tYmluZSBhbGwgY291bnQgdGFibGVzIGludG8gb25lIGRhdGEgZnJhbWUKY29tYmluZWRfY291bnRfdGFibGUgPC0gZG8uY2FsbChyYmluZCwgY291bnRfdGFibGVzKQoKIyBSZW5hbWUgdGhlIHJvd25hbWVzIGJhc2VkIG9uIHRoZSBjb3VudCB0YWJsZSBudW1iZXIKcm93bmFtZXMoY29tYmluZWRfY291bnRfdGFibGUpIDwtIHBhc3RlMCgiU2JqIiwgcmVwKDE6NTAsIGVhY2ggPSBucm93KGNvdW50X3RhYmxlc1tbMV1dKSksICJfVGltZSIsIDE6MTApCgpgYGAKCgpfX0NyZWF0ZSBGYWtlIE1ldGFkYXRhX18gIAoxLiBTZXggKE0gb3IgRiwgNTAvNTAgUmF0aW8pCjIuIEFnZSAtIHNhbXBsZSBmcm9tIGJldHdlZW4gMTggYW5kIDQ1CjMuIEJNSSAtIHNhbXBsZSBiZXR3ZWVuIDE4IGFuZCAzNQoKTWFrZSBNZXRhZGF0YSBhbmQgbWVyZ2Ugd2l0aCB0aGUgY291bnQgZGF0YQpgYGB7cn0KbWV0YV9kYXRhIDwtICBleHBhbmQuZ3JpZChUaW1lID0gMToxMCxJRCA9IDE6NTApCnJvd25hbWVzKG1ldGFfZGF0YSkgPC0gcm93bmFtZXMoY29tYmluZWRfY291bnRfdGFibGUpCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRTZXggPC0gcmVwKGMoMCwgMSksIGVhY2ggPSA1MCkKIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKbWV0YV9kYXRhJEFnZSA8LSByZXAoc2FtcGxlKDE4OjQ1LCA1MCwgcmVwbGFjZSA9IFRSVUUpLCBlYWNoID0gMTApCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRCTUkgPC0gcmVwKHNhbXBsZSgxODozNSwgNTAsIHJlcGxhY2UgPSBUUlVFKSwgZWFjaCA9IDEwKQoKIyBDZW50ZXIgdGhlIGNvbnRpbnVvdXMgdmFyaWFibGVzCm1ldGFfZGF0YSRBZ2UgPC0gbWV0YV9kYXRhJEFnZSAtIG1lYW4obWV0YV9kYXRhJEFnZSkKbWV0YV9kYXRhJEJNSSA8LSBtZXRhX2RhdGEkQk1JIC0gbWVhbihtZXRhX2RhdGEkQk1JKQoKCiMgRGYgMiBpcyBNZXRhZGF0YSBtZXJnZWQgd2l0aCBDb3VudHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI1JvdW5kIG9mZiBhbmQgaW5jcmVhc2UKY29tYmluZWRfY291bnRfdGFibGUgPC0gYXMuZGF0YS5mcmFtZShjb21iaW5lZF9jb3VudF90YWJsZSArIGFicyhtaW4oY29tYmluZWRfY291bnRfdGFibGUpKSkKY29tYmluZWRfY291bnRfdGFibGUgPC0gKGNvbWJpbmVkX2NvdW50X3RhYmxlKSoxMAptZXRhX2NvdW50cyA8LSBiYXNlOjptZXJnZShtZXRhX2RhdGEsIGNvbWJpbmVkX2NvdW50X3RhYmxlLCBieSA9InJvdy5uYW1lcyIsIGFsbCA9IFRSVUUpCm1ldGFfY291bnRzIDwtIGNvbHVtbl90b19yb3duYW1lcyhtZXRhX2NvdW50cywgIlJvdy5uYW1lcyIpCgoKYGBgCgoKQWRkIGluIGJpb2xvZ2ljYWwgY292YXJpYXRlcwpgYGB7cn0KIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKIyBBZGRpbiBjb3ZhcmlhdGVzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBTZXQgdXAgbmV3IGRhdGFmcmFtZQpMb25nX2RhdGFfbmV3IDwtIG1ldGFfY291bnRzCgoKIyBMb29wIHJ1bm5pbmcgdGhlIExNIHRvIGdldCBuZXcgdmFyaWFibGVzIHdpdGggZXJyb3IgdGhhdCBoYXMgYSByYW5nZSBvZiB2YWx1ZXMKIyBUYXhhIDIxIC0gMzAgd2lsbCBoYXZlIFNleCBlZmZlY3QKZm9yIChpIGluIDI2OjM1KSB7CiAgZXJyb3IgPC0gcm5vcm0obnJvdyhMb25nX2RhdGFfbmV3KSwgbWVhbiA9IDEsIHNkID0gMC42KQogIExvbmdfZGF0YV9uZXdbLCBpXSA8LSBMb25nX2RhdGFfbmV3WywgaV0gKyAwLjAxICogTG9uZ19kYXRhX25ldyRTZXggKyBlcnJvcgp9CgojIHJvdW5kIHRoZSBjb3VudHMgdG8gYnJpbmcgdGhlbSBiYWNrIHVwIHRvIDAKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBBZGQgdGhlIG1pbmltdW0gdmFsdWUgdG8gYnJpbmcgZXZlcnl0aGluZyB1cCB0byBhdCBsZWFzdCAwCmNvdW50X3RhYmxlMSA8LSBMb25nX2RhdGFfbmV3Wyw2OjU1XQoKCiMgc2NhbGUgdG8gcG9zaXRpdmUgYW5kIG1ha2UgbGFyZ2VyCmNvdW50X3RhYmxlMSA8LSBjb3VudF90YWJsZTEgKyBhYnMobWluKGNvdW50X3RhYmxlMSkpCmNvdW50X3RhYmxlMSA8LSByb3VuZChjb3VudF90YWJsZTEqMTApCgojY2hhbmdlIExvbmdfZGF0YV9uZXcKTG9uZ19kYXRhX25ld1ssNjo1NV0gPC0gY291bnRfdGFibGUxCmBgYAoKCgpOb3cgQWRkIGluIDBzCmBgYHtyfQojIFNldCB1cCBuZXcgZGF0YWZyYW1lCnByZWRhdGFfMCA8LSBjb3VudF90YWJsZTEKCiMgQWRkIHRoZSAwcyBiYWNrIGluCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCgojIFN0ZXAgMTogQ2FsY3VsYXRlIHRvdGFsIGNvdW50cyBmb3IgZWFjaCBjb2x1bW4KdG90YWxfY291bnRzIDwtIGNvbFN1bXMocHJlZGF0YV8wKQoKCiMgU3RlcCAyOiBDcmVhdGUgcHJvYmFiaWxpdHkgZ3JhZGllbnQKZ3JhZGllbnQgPC0gc2VxKDAuNSwgMC4yLCBsZW5ndGgub3V0ID0gbmNvbChwcmVkYXRhXzApKQoKIyBTdGVwIDM6IE1ha2UgdGhlIHByb2JhYmlsaXR5IGdyYWRpZW50IGludmVyc2UgdG8gdG90YWwgY291bnRzIChpZSBoaWdoZXIgdG90YWwgdmFsdWUsIGxvd2VyIHByb3BvcnRpb24gb2YgMHMpCnRvdGFsX2NvdW50cyA8LSB0b3RhbF9jb3VudHNbb3JkZXIodG90YWxfY291bnRzKV0KZ3JhZGllbnQgPC0gZ3JhZGllbnRbb3JkZXIoLWdyYWRpZW50KV0KCiMgU3RlcCA0ICYgNTogR2VuZXJhdGUgcmFuZG9tIG51bWJlcnMgYW5kIHNldCBjb3VudHMgdG8gMCBiYXNlZCBvbiBwcm9iYWJpbGl0eSBncmFkaWVudAoKZm9yIChpIGluIHNlcV9hbG9uZyh0b3RhbF9jb3VudHMpKSB7CiAgcHJvYiA8LSBncmFkaWVudFtpXQogICMgQ2FsY3VsYXRlIG51bWJlciBvZiAwcyB0byBhZGQgYmFzZWQgb24gcHJvYmFiaWxpdHkKICBudW1femVyb3MgPC0gc3VtKHJ1bmlmKG5yb3cocHJlZGF0YV8wKSkgPD0gcHJvYikKICAjIFJhbmRvbWx5IHNlbGVjdCByb3dzIHRvIHNldCB0byAwCiAgIyBTZXQgc2VlZAogIHNldC5zZWVkKDEyMzQ1K2kpCiAgcm93c190b196ZXJvIDwtIHNhbXBsZShucm93KHByZWRhdGFfMCksIG51bV96ZXJvcykKICAjIFNldCBjb3VudHMgdG8gMAogIHByZWRhdGFfMFtyb3dzX3RvX3plcm8sIGldIDwtIDAKfQoKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIGZvciBwbG90dGluZwp6ZXJvX2RhdGExIDwtIG1lcmdlKG1ldGFfZGF0YSwgcHJlZGF0YV8wLCBieSA9IDApCnplcm9fZGF0YTEgPC0gY29sdW1uX3RvX3Jvd25hbWVzKHplcm9fZGF0YTEsICJSb3cubmFtZXMiKQojcm91bmQgdGhlIGNvdW50cwp6ZXJvX2RhdGExWyw2OjU1XSA8LSByb3VuZCh6ZXJvX2RhdGExWyw2OjU1XSkKYGBgCgpHcmFwaHMgdG8gQ2hlY2sKYGBge3J9CiMgSW5kaXZpZHVhbCBTcGVjaWVzIFBsb3RzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUGl2b3QgdG8gbG9uZyBkYXRhCmNvdW50X2xvbmcgPC0gdGlkeXI6OnBpdm90X2xvbmdlcih6ZXJvX2RhdGExLCBjb2xzID0gc3RhcnRzX3dpdGgoInNwIiksIG5hbWVzX3RvID0gIlNwZWNpZXMiKQoKIyBQbG90IHRoZSBkYXRhCmNvdW50X2xvbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVGltZSwgeSA9IHZhbHVlLCBjb2xvdXIgPSBhcy5mYWN0b3IoSUQpLAogICAgICAgICAgICAgZ3JvdXAgPSBhcy5mYWN0b3IoSUQpLCBsaW5ldHlwZSA9IGFzLmZhY3RvcihJRCkpKSArCiAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21faml0dGVyKCkgKwogIHlsYWIoIkNvdW50IikgKwogIGxhYnMobGluZXR5cGUgPSAiSUQiLCBjb2xvciA9ICJJRCIpICsKICBmYWNldF93cmFwKH4gU3BlY2llcykgKyAgIyBDcmVhdGUgYSBwYW5lbCBmb3IgZWFjaCBzcGVjaWVzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZ2d0aXRsZSgiVGltZSBTZXJpZXMgb2YgTj01MCwgMHMiKQoKCiMgRGlzdHJpYnV0aW9uIG9mIGNvdW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpoaXN0KGFzLm1hdHJpeCh6ZXJvX2RhdGExWyw2OjU1XSksIGJyZWFrcyA9IDEwMCwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgR0xWIERhdGEiLCB4bGFiID0gIkNvdW50cyIpCgojIENvcnJlbGF0aW9uIG1hdHJpeApjb3JfcmF3MSA8LSBjb3IoKHplcm9fZGF0YTFbLDY6NTVdKSwgbWV0aG9kID0gInNwZWFybWFuIikKaGVhdG1hcChjb3JfcmF3MSwgQ29sdiA9IE5BLCBSb3d2ID0gTkEsIG1haW4gPSAiQ29ycmVsYXRpb24gb2YgMCBpbmZsYXRlZCBubyBjb3ZhcmlhdGVzIikKYGBgCgoKU2F2ZSB0aGUgQ291bnRzCmBgYHtyfQp3cml0ZS5jc3YobWV0YV9jb3VudHMsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfMC4wMS5jc3YiKSkKd3JpdGUuY3N2KExvbmdfZGF0YV9uZXcsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfQ292XzAuMDEuY3N2IikpCndyaXRlLmNzdih6ZXJvX2RhdGExLCBoZXJlKCJEYXRhIiwiR0xWX1NpbURhdGEiLCAiRGF0YXNldF81IiwiR0xWX0Nvdlplcm9fMC4wMS5jc3YiKSkKYGBgCgoKCiMgMy4gU2ltdWxhdGUgYmV0YSA9IDAuMTAKKioqIAoKX19TaW11bGF0ZSBDb3VudHNfXyAgClNpbXVsYXRlIEdMViBmb3IgNTAgaW5kaXZpZHVhbHMsIDUwIHNwZWNpZXMsIDEwIHRpbWVwb2ludHMsIENvbm5lY3RhbmNlID0gMC45MCwgU2V4IEJldGEgPSAwLjEKYGBge3J9CiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCgojIFN0ZXAgMSBSdW4gR0xWIGZvciBuIG51bWJlciBvZiBzdWJqZWN0IGFuZCB0aW1lcG9pbnRzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgR2VuZXJhdGUgaW50ZXJhY3Rpb25zIGZyb20gdW5pZm9ybSBkaXN0cmlidXRpb24KQV91bmlmb3JtIDwtIHJhbmRvbUEoCiAgICBuX3NwZWNpZXMgPSA1MCwKICAgIGRpYWdvbmFsID0gLTEuMCwKICAgIGNvbm5lY3RhbmNlID0gMC45MCkKCiMgQ3JlYXRlIGFuIGVtcHR5IGxpc3QgdG8gc3RvcmUgdGhlIGNvdW50IHRhYmxlcyBmb3IgZWFjaCBzdWJqZWN0CmNvdW50X3RhYmxlcyA8LSBsaXN0KCkKCgojIExvb3AgdGhyb3VnaCA1MCBzdWJqZWN0cyBhbmQgZ2VuZXJhdGUgY291bnQgdGFibGVzIGZvciBlYWNoCmZvciAoaSBpbiAxOjUwKSB7CiAgIyBTZXQgdGhlIHNlZWQgZm9yIGVhY2ggc3ViamVjdAogIHNldC5zZWVkKDEyMzQ1ICsgaSkgIAogIyBHZW5lcmFsaXplZCBMb3RrYS1Wb2x0ZXJyYSAoZ0xWKQogIHRzZV9nbHYgPC0gc2ltdWxhdGVHTFYobl9zcGVjaWVzID0gNTAsCiAgICAgICAgICAgICAgICAgICAgICAgQSA9IEFfdW5pZm9ybSwKICAgICAgICAgICAgICAgICAgICAgICB0X3N0YXJ0ID0gMCwgCiAgICAgICAgICAgICAgICAgICAgICAgdF9zdG9yZSA9IDEwLAogICAgICAgICAgICAgICAgICAgICAgIHN0b2NoYXN0aWMgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBub3JtID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JfdmFyaWFuY2UgPSAwLjAxKQogIAogICMgR2V0IHRoZSBjb3VudCB0YWJsZQogIHNpbV9kYXRhIDwtIHRzZV9nbHZAYXNzYXlzQGRhdGFAbGlzdERhdGFbWyJjb3VudHMiXV0KICAKICAjIFN0b3JlIHRoZSBjb3VudCB0YWJsZSBpbiB0aGUgbGlzdAogIGNvdW50X3RhYmxlc1tbaV1dIDwtIHQoc2ltX2RhdGEpCn0KCiMgU3RlcCAyIC0gTWVyZ2UgdG9nZXRoZXIKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIENvbWJpbmUgYWxsIGNvdW50IHRhYmxlcyBpbnRvIG9uZSBkYXRhIGZyYW1lCmNvbWJpbmVkX2NvdW50X3RhYmxlIDwtIGRvLmNhbGwocmJpbmQsIGNvdW50X3RhYmxlcykKCiMgUmVuYW1lIHRoZSByb3duYW1lcyBiYXNlZCBvbiB0aGUgY291bnQgdGFibGUgbnVtYmVyCnJvd25hbWVzKGNvbWJpbmVkX2NvdW50X3RhYmxlKSA8LSBwYXN0ZTAoIlNiaiIsIHJlcCgxOjUwLCBlYWNoID0gbnJvdyhjb3VudF90YWJsZXNbWzFdXSkpLCAiX1RpbWUiLCAxOjEwKQoKYGBgCgoKX19DcmVhdGUgRmFrZSBNZXRhZGF0YV9fICAKMS4gU2V4IChNIG9yIEYsIDUwLzUwIFJhdGlvKQoyLiBBZ2UgLSBzYW1wbGUgZnJvbSBiZXR3ZWVuIDE4IGFuZCA0NQozLiBCTUkgLSBzYW1wbGUgYmV0d2VlbiAxOCBhbmQgMzUKCk1ha2UgTWV0YWRhdGEgYW5kIG1lcmdlIHdpdGggdGhlIGNvdW50IGRhdGEKYGBge3J9CiMgRGYgMSBpcyBNZXRhZGF0YQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwptZXRhX2RhdGEgPC0gIGV4cGFuZC5ncmlkKFRpbWUgPSAxOjEwLElEID0gMTo1MCkKcm93bmFtZXMobWV0YV9kYXRhKSA8LSByb3duYW1lcyhjb21iaW5lZF9jb3VudF90YWJsZSkKIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKbWV0YV9kYXRhJFNleCA8LSByZXAoYygwLCAxKSwgZWFjaCA9IDUwKQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQptZXRhX2RhdGEkQWdlIDwtIHJlcChzYW1wbGUoMTg6NDUsIDUwLCByZXBsYWNlID0gVFJVRSksIGVhY2ggPSAxMCkKIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKbWV0YV9kYXRhJEJNSSA8LSByZXAoc2FtcGxlKDE4OjM1LCA1MCwgcmVwbGFjZSA9IFRSVUUpLCBlYWNoID0gMTApCgojIENlbnRlciB0aGUgY29udGludW91cyB2YXJpYWJsZXMKbWV0YV9kYXRhJEFnZSA8LSBtZXRhX2RhdGEkQWdlIC0gbWVhbihtZXRhX2RhdGEkQWdlKQptZXRhX2RhdGEkQk1JIDwtIG1ldGFfZGF0YSRCTUkgLSBtZWFuKG1ldGFfZGF0YSRCTUkpCgoKIyBEZiAyIGlzIE1ldGFkYXRhIG1lcmdlZCB3aXRoIENvdW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojUm91bmQgb2ZmIGFuZCBpbmNyZWFzZQpjb21iaW5lZF9jb3VudF90YWJsZSA8LSBhcy5kYXRhLmZyYW1lKGNvbWJpbmVkX2NvdW50X3RhYmxlICsgYWJzKG1pbihjb21iaW5lZF9jb3VudF90YWJsZSkpKQpjb21iaW5lZF9jb3VudF90YWJsZSA8LSAoY29tYmluZWRfY291bnRfdGFibGUpKjEwCm1ldGFfY291bnRzIDwtIGJhc2U6Om1lcmdlKG1ldGFfZGF0YSwgY29tYmluZWRfY291bnRfdGFibGUsIGJ5ID0icm93Lm5hbWVzIiwgYWxsID0gVFJVRSkKbWV0YV9jb3VudHMgPC0gY29sdW1uX3RvX3Jvd25hbWVzKG1ldGFfY291bnRzLCAiUm93Lm5hbWVzIikKCgpgYGAKCgpBZGQgaW4gYmlvbG9naWNhbCBjb3ZhcmlhdGVzCmBgYHtyfQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQojIEFkZGluIGNvdmFyaWF0ZXMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIFNldCB1cCBuZXcgZGF0YWZyYW1lCkxvbmdfZGF0YV9uZXcgPC0gbWV0YV9jb3VudHMKCgojIExvb3AgcnVubmluZyB0aGUgTE0gdG8gZ2V0IG5ldyB2YXJpYWJsZXMgd2l0aCBlcnJvciB0aGF0IGhhcyBhIHJhbmdlIG9mIHZhbHVlcwojIFRheGEgMjEgLSAzMCB3aWxsIGhhdmUgU2V4IGVmZmVjdApmb3IgKGkgaW4gMjY6MzUpIHsKICBlcnJvciA8LSBybm9ybShucm93KExvbmdfZGF0YV9uZXcpLCBtZWFuID0gMSwgc2QgPSAwLjYpCiAgTG9uZ19kYXRhX25ld1ssIGldIDwtIExvbmdfZGF0YV9uZXdbLCBpXSArIDAuMSAqIExvbmdfZGF0YV9uZXckU2V4ICsgZXJyb3IKfQoKIyByb3VuZCB0aGUgY291bnRzIHRvIGJyaW5nIHRoZW0gYmFjayB1cCB0byAwCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgQWRkIHRoZSBtaW5pbXVtIHZhbHVlIHRvIGJyaW5nIGV2ZXJ5dGhpbmcgdXAgdG8gYXQgbGVhc3QgMApjb3VudF90YWJsZTEgPC0gTG9uZ19kYXRhX25ld1ssNjo1NV0KCgojIHNjYWxlIHRvIHBvc2l0aXZlIGFuZCBtYWtlIGxhcmdlcgpjb3VudF90YWJsZTEgPC0gY291bnRfdGFibGUxICsgYWJzKG1pbihjb3VudF90YWJsZTEpKQpjb3VudF90YWJsZTEgPC0gcm91bmQoY291bnRfdGFibGUxKjEwKQoKI2NoYW5nZSBMb25nX2RhdGFfbmV3CkxvbmdfZGF0YV9uZXdbLDY6NTVdIDwtIGNvdW50X3RhYmxlMQpgYGAKCgoKTm93IEFkZCBpbiAwcwpgYGB7cn0KIyBTZXQgdXAgbmV3IGRhdGFmcmFtZQpwcmVkYXRhXzAgPC0gY291bnRfdGFibGUxCgojIEFkZCB0aGUgMHMgYmFjayBpbgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgoKIyBTdGVwIDE6IENhbGN1bGF0ZSB0b3RhbCBjb3VudHMgZm9yIGVhY2ggY29sdW1uCnRvdGFsX2NvdW50cyA8LSBjb2xTdW1zKHByZWRhdGFfMCkKCgojIFN0ZXAgMjogQ3JlYXRlIHByb2JhYmlsaXR5IGdyYWRpZW50CmdyYWRpZW50IDwtIHNlcSgwLjUsIDAuMiwgbGVuZ3RoLm91dCA9IG5jb2wocHJlZGF0YV8wKSkKCiMgU3RlcCAzOiBNYWtlIHRoZSBwcm9iYWJpbGl0eSBncmFkaWVudCBpbnZlcnNlIHRvIHRvdGFsIGNvdW50cyAoaWUgaGlnaGVyIHRvdGFsIHZhbHVlLCBsb3dlciBwcm9wb3J0aW9uIG9mIDBzKQp0b3RhbF9jb3VudHMgPC0gdG90YWxfY291bnRzW29yZGVyKHRvdGFsX2NvdW50cyldCmdyYWRpZW50IDwtIGdyYWRpZW50W29yZGVyKC1ncmFkaWVudCldCgojIFN0ZXAgNCAmIDU6IEdlbmVyYXRlIHJhbmRvbSBudW1iZXJzIGFuZCBzZXQgY291bnRzIHRvIDAgYmFzZWQgb24gcHJvYmFiaWxpdHkgZ3JhZGllbnQKCmZvciAoaSBpbiBzZXFfYWxvbmcodG90YWxfY291bnRzKSkgewogIHByb2IgPC0gZ3JhZGllbnRbaV0KICAjIENhbGN1bGF0ZSBudW1iZXIgb2YgMHMgdG8gYWRkIGJhc2VkIG9uIHByb2JhYmlsaXR5CiAgbnVtX3plcm9zIDwtIHN1bShydW5pZihucm93KHByZWRhdGFfMCkpIDw9IHByb2IpCiAgIyBSYW5kb21seSBzZWxlY3Qgcm93cyB0byBzZXQgdG8gMAogICMgU2V0IHRoZSBzZWVkIGZvciBlYWNoIHN1YmplY3QKICBzZXQuc2VlZCgxMjM0NSArIGkpICAKICByb3dzX3RvX3plcm8gPC0gc2FtcGxlKG5yb3cocHJlZGF0YV8wKSwgbnVtX3plcm9zKQogICMgU2V0IGNvdW50cyB0byAwCiAgcHJlZGF0YV8wW3Jvd3NfdG9femVybywgaV0gPC0gMAp9CgojIG1lcmdlIHdpdGggbWV0YWRhdGEgZm9yIHBsb3R0aW5nCnplcm9fZGF0YTEgPC0gbWVyZ2UobWV0YV9kYXRhLCBwcmVkYXRhXzAsIGJ5ID0gMCkKemVyb19kYXRhMSA8LSBjb2x1bW5fdG9fcm93bmFtZXMoemVyb19kYXRhMSwgIlJvdy5uYW1lcyIpCiNyb3VuZCB0aGUgY291bnRzCnplcm9fZGF0YTFbLDY6NTVdIDwtIHJvdW5kKHplcm9fZGF0YTFbLDY6NTVdKQpgYGAKCkdyYXBocyB0byBDaGVjawpgYGB7cn0KIyBJbmRpdmlkdWFsIFNwZWNpZXMgUGxvdHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBQaXZvdCB0byBsb25nIGRhdGEKY291bnRfbG9uZyA8LSB0aWR5cjo6cGl2b3RfbG9uZ2VyKHplcm9fZGF0YTEsIGNvbHMgPSBzdGFydHNfd2l0aCgic3AiKSwgbmFtZXNfdG8gPSAiU3BlY2llcyIpCgojIFBsb3QgdGhlIGRhdGEKY291bnRfbG9uZyAlPiUKICBnZ3Bsb3QoYWVzKHggPSBUaW1lLCB5ID0gdmFsdWUsIGNvbG91ciA9IGFzLmZhY3RvcihJRCksCiAgICAgICAgICAgICBncm91cCA9IGFzLmZhY3RvcihJRCksIGxpbmV0eXBlID0gYXMuZmFjdG9yKElEKSkpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9qaXR0ZXIoKSArCiAgeWxhYigiQ291bnQiKSArCiAgbGFicyhsaW5ldHlwZSA9ICJJRCIsIGNvbG9yID0gIklEIikgKwogIGZhY2V0X3dyYXAofiBTcGVjaWVzKSArICAjIENyZWF0ZSBhIHBhbmVsIGZvciBlYWNoIHNwZWNpZXMKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICBnZ3RpdGxlKCJUaW1lIFNlcmllcyBvZiBOPTUwLCAwcyIpCgoKIyBEaXN0cmlidXRpb24gb2YgY291bnRzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCmhpc3QoYXMubWF0cml4KHplcm9fZGF0YTFbLDY6NTVdKSwgYnJlYWtzID0gMTAwLCBtYWluID0gIkRpc3RyaWJ1dGlvbiBvZiBHTFYgRGF0YSIsIHhsYWIgPSAiQ291bnRzIikKCiMgQ29ycmVsYXRpb24gbWF0cml4CmNvcl9yYXcxIDwtIGNvcigoemVyb19kYXRhMVssNjo1NV0pLCBtZXRob2QgPSAic3BlYXJtYW4iKQpoZWF0bWFwKGNvcl9yYXcxLCBDb2x2ID0gTkEsIFJvd3YgPSBOQSwgbWFpbiA9ICJDb3JyZWxhdGlvbiBvZiAwIGluZmxhdGVkIG5vIGNvdmFyaWF0ZXMiKQpgYGAKCgpTYXZlIHRoZSBDb3VudHMKYGBge3J9CndyaXRlLmNzdihtZXRhX2NvdW50cywgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl8wLjEwLmNzdiIpKQp3cml0ZS5jc3YoTG9uZ19kYXRhX25ldywgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl9Db3ZfMC4xMC5jc3YiKSkKd3JpdGUuY3N2KHplcm9fZGF0YTEsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfQ292WmVyb18wLjEwLmNzdiIpKQpgYGAKCgoKIyA0LiBTaW11bGF0ZSBiZXRhID0gMS4wCioqKiAKCl9fU2ltdWxhdGUgQ291bnRzX18gIApTaW11bGF0ZSBHTFYgZm9yIDUwIGluZGl2aWR1YWxzLCA1MCBzcGVjaWVzLCAxMCB0aW1lcG9pbnRzLCBDb25uZWN0YW5jZSA9IDAuOTAsIFNleCBCZXRhID0gMS4wCmBgYHtyfQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQoKIyBTdGVwIDEgUnVuIEdMViBmb3IgbiBudW1iZXIgb2Ygc3ViamVjdCBhbmQgdGltZXBvaW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIEdlbmVyYXRlIGludGVyYWN0aW9ucyBmcm9tIHVuaWZvcm0gZGlzdHJpYnV0aW9uCkFfdW5pZm9ybSA8LSByYW5kb21BKAogICAgbl9zcGVjaWVzID0gNTAsCiAgICBkaWFnb25hbCA9IC0xLjAsCiAgICBjb25uZWN0YW5jZSA9IDAuOTApCgojIENyZWF0ZSBhbiBlbXB0eSBsaXN0IHRvIHN0b3JlIHRoZSBjb3VudCB0YWJsZXMgZm9yIGVhY2ggc3ViamVjdApjb3VudF90YWJsZXMgPC0gbGlzdCgpCgoKIyBMb29wIHRocm91Z2ggNTAgc3ViamVjdHMgYW5kIGdlbmVyYXRlIGNvdW50IHRhYmxlcyBmb3IgZWFjaApmb3IgKGkgaW4gMTo1MCkgewogICMgU2V0IHRoZSBzZWVkIGZvciBlYWNoIHN1YmplY3QKICBzZXQuc2VlZCgxMjM0NSArIGkpICAKICMgR2VuZXJhbGl6ZWQgTG90a2EtVm9sdGVycmEgKGdMVikKICB0c2VfZ2x2IDwtIHNpbXVsYXRlR0xWKG5fc3BlY2llcyA9IDUwLAogICAgICAgICAgICAgICAgICAgICAgIEEgPSBBX3VuaWZvcm0sCiAgICAgICAgICAgICAgICAgICAgICAgdF9zdGFydCA9IDAsIAogICAgICAgICAgICAgICAgICAgICAgIHRfc3RvcmUgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICBzdG9jaGFzdGljID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgbm9ybSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGVycm9yX3ZhcmlhbmNlID0gMC4wMSkKICAKICAjIEdldCB0aGUgY291bnQgdGFibGUKICBzaW1fZGF0YSA8LSB0c2VfZ2x2QGFzc2F5c0BkYXRhQGxpc3REYXRhW1siY291bnRzIl1dCiAgCiAgIyBTdG9yZSB0aGUgY291bnQgdGFibGUgaW4gdGhlIGxpc3QKICBjb3VudF90YWJsZXNbW2ldXSA8LSB0KHNpbV9kYXRhKQp9CgojIFN0ZXAgMiAtIE1lcmdlIHRvZ2V0aGVyCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBDb21iaW5lIGFsbCBjb3VudCB0YWJsZXMgaW50byBvbmUgZGF0YSBmcmFtZQpjb21iaW5lZF9jb3VudF90YWJsZSA8LSBkby5jYWxsKHJiaW5kLCBjb3VudF90YWJsZXMpCgojIFJlbmFtZSB0aGUgcm93bmFtZXMgYmFzZWQgb24gdGhlIGNvdW50IHRhYmxlIG51bWJlcgpyb3duYW1lcyhjb21iaW5lZF9jb3VudF90YWJsZSkgPC0gcGFzdGUwKCJTYmoiLCByZXAoMTo1MCwgZWFjaCA9IG5yb3coY291bnRfdGFibGVzW1sxXV0pKSwgIl9UaW1lIiwgMToxMCkKCmBgYAoKCl9fQ3JlYXRlIEZha2UgTWV0YWRhdGFfXyAgCjEuIFNleCAoTSBvciBGLCA1MC81MCBSYXRpbykKMi4gQWdlIC0gc2FtcGxlIGZyb20gYmV0d2VlbiAxOCBhbmQgNDUKMy4gQk1JIC0gc2FtcGxlIGJldHdlZW4gMTggYW5kIDM1CgpNYWtlIE1ldGFkYXRhIGFuZCBtZXJnZSB3aXRoIHRoZSBjb3VudCBkYXRhCmBgYHtyfQojIERmIDEgaXMgTWV0YWRhdGEKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKbWV0YV9kYXRhIDwtICBleHBhbmQuZ3JpZChUaW1lID0gMToxMCxJRCA9IDE6NTApCnJvd25hbWVzKG1ldGFfZGF0YSkgPC0gcm93bmFtZXMoY29tYmluZWRfY291bnRfdGFibGUpCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRTZXggPC0gcmVwKGMoMCwgMSksIGVhY2ggPSA1MCkKIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKbWV0YV9kYXRhJEFnZSA8LSByZXAoc2FtcGxlKDE4OjQ1LCA1MCwgcmVwbGFjZSA9IFRSVUUpLCBlYWNoID0gMTApCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRCTUkgPC0gcmVwKHNhbXBsZSgxODozNSwgNTAsIHJlcGxhY2UgPSBUUlVFKSwgZWFjaCA9IDEwKQoKIyBDZW50ZXIgdGhlIGNvbnRpbnVvdXMgdmFyaWFibGVzCm1ldGFfZGF0YSRBZ2UgPC0gbWV0YV9kYXRhJEFnZSAtIG1lYW4obWV0YV9kYXRhJEFnZSkKbWV0YV9kYXRhJEJNSSA8LSBtZXRhX2RhdGEkQk1JIC0gbWVhbihtZXRhX2RhdGEkQk1JKQoKCiMgRGYgMiBpcyBNZXRhZGF0YSBtZXJnZWQgd2l0aCBDb3VudHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI1JvdW5kIG9mZiBhbmQgaW5jcmVhc2UKY29tYmluZWRfY291bnRfdGFibGUgPC0gYXMuZGF0YS5mcmFtZShjb21iaW5lZF9jb3VudF90YWJsZSArIGFicyhtaW4oY29tYmluZWRfY291bnRfdGFibGUpKSkKY29tYmluZWRfY291bnRfdGFibGUgPC0gKGNvbWJpbmVkX2NvdW50X3RhYmxlKSoxMAptZXRhX2NvdW50cyA8LSBiYXNlOjptZXJnZShtZXRhX2RhdGEsIGNvbWJpbmVkX2NvdW50X3RhYmxlLCBieSA9InJvdy5uYW1lcyIsIGFsbCA9IFRSVUUpCm1ldGFfY291bnRzIDwtIGNvbHVtbl90b19yb3duYW1lcyhtZXRhX2NvdW50cywgIlJvdy5uYW1lcyIpCgoKYGBgCgoKQWRkIGluIGJpb2xvZ2ljYWwgY292YXJpYXRlcwpgYGB7cn0KIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKIyBBZGRpbiBjb3ZhcmlhdGVzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyBTZXQgdXAgbmV3IGRhdGFmcmFtZQpMb25nX2RhdGFfbmV3IDwtIG1ldGFfY291bnRzCgoKIyBMb29wIHJ1bm5pbmcgdGhlIExNIHRvIGdldCBuZXcgdmFyaWFibGVzIHdpdGggZXJyb3IgdGhhdCBoYXMgYSByYW5nZSBvZiB2YWx1ZXMKIyBUYXhhIDIxIC0gMzAgd2lsbCBoYXZlIFNleCBlZmZlY3QKZm9yIChpIGluIDI2OjM1KSB7CiAgZXJyb3IgPC0gcm5vcm0obnJvdyhMb25nX2RhdGFfbmV3KSwgbWVhbiA9IDEsIHNkID0gMC42KQogIExvbmdfZGF0YV9uZXdbLCBpXSA8LSBMb25nX2RhdGFfbmV3WywgaV0gKyAxLjAgKiBMb25nX2RhdGFfbmV3JFNleCArIGVycm9yCn0KCiMgcm91bmQgdGhlIGNvdW50cyB0byBicmluZyB0aGVtIGJhY2sgdXAgdG8gMAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIEFkZCB0aGUgbWluaW11bSB2YWx1ZSB0byBicmluZyBldmVyeXRoaW5nIHVwIHRvIGF0IGxlYXN0IDAKY291bnRfdGFibGUxIDwtIExvbmdfZGF0YV9uZXdbLDY6NTVdCgoKIyBzY2FsZSB0byBwb3NpdGl2ZSBhbmQgbWFrZSBsYXJnZXIKY291bnRfdGFibGUxIDwtIGNvdW50X3RhYmxlMSArIGFicyhtaW4oY291bnRfdGFibGUxKSkKY291bnRfdGFibGUxIDwtIHJvdW5kKGNvdW50X3RhYmxlMSoxMCkKCiNjaGFuZ2UgTG9uZ19kYXRhX25ldwpMb25nX2RhdGFfbmV3Wyw2OjU1XSA8LSBjb3VudF90YWJsZTEKYGBgCgoKCk5vdyBBZGQgaW4gMHMKYGBge3J9CiMgU2V0IHVwIG5ldyBkYXRhZnJhbWUKcHJlZGF0YV8wIDwtIGNvdW50X3RhYmxlMQoKIyBBZGQgdGhlIDBzIGJhY2sgaW4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiMgU3RlcCAxOiBDYWxjdWxhdGUgdG90YWwgY291bnRzIGZvciBlYWNoIGNvbHVtbgp0b3RhbF9jb3VudHMgPC0gY29sU3VtcyhwcmVkYXRhXzApCgoKIyBTdGVwIDI6IENyZWF0ZSBwcm9iYWJpbGl0eSBncmFkaWVudApncmFkaWVudCA8LSBzZXEoMC41LCAwLjIsIGxlbmd0aC5vdXQgPSBuY29sKHByZWRhdGFfMCkpCgojIFN0ZXAgMzogTWFrZSB0aGUgcHJvYmFiaWxpdHkgZ3JhZGllbnQgaW52ZXJzZSB0byB0b3RhbCBjb3VudHMgKGllIGhpZ2hlciB0b3RhbCB2YWx1ZSwgbG93ZXIgcHJvcG9ydGlvbiBvZiAwcykKdG90YWxfY291bnRzIDwtIHRvdGFsX2NvdW50c1tvcmRlcih0b3RhbF9jb3VudHMpXQpncmFkaWVudCA8LSBncmFkaWVudFtvcmRlcigtZ3JhZGllbnQpXQoKIyBTdGVwIDQgJiA1OiBHZW5lcmF0ZSByYW5kb20gbnVtYmVycyBhbmQgc2V0IGNvdW50cyB0byAwIGJhc2VkIG9uIHByb2JhYmlsaXR5IGdyYWRpZW50Cgpmb3IgKGkgaW4gc2VxX2Fsb25nKHRvdGFsX2NvdW50cykpIHsKICBwcm9iIDwtIGdyYWRpZW50W2ldCiAgIyBDYWxjdWxhdGUgbnVtYmVyIG9mIDBzIHRvIGFkZCBiYXNlZCBvbiBwcm9iYWJpbGl0eQogIG51bV96ZXJvcyA8LSBzdW0ocnVuaWYobnJvdyhwcmVkYXRhXzApKSA8PSBwcm9iKQogICMgUmFuZG9tbHkgc2VsZWN0IHJvd3MgdG8gc2V0IHRvIDAKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAgcm93c190b196ZXJvIDwtIHNhbXBsZShucm93KHByZWRhdGFfMCksIG51bV96ZXJvcykKICAjIFNldCBjb3VudHMgdG8gMAogIHByZWRhdGFfMFtyb3dzX3RvX3plcm8sIGldIDwtIDAKfQoKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIGZvciBwbG90dGluZwp6ZXJvX2RhdGExIDwtIG1lcmdlKG1ldGFfZGF0YSwgcHJlZGF0YV8wLCBieSA9IDApCnplcm9fZGF0YTEgPC0gY29sdW1uX3RvX3Jvd25hbWVzKHplcm9fZGF0YTEsICJSb3cubmFtZXMiKQojcm91bmQgdGhlIGNvdW50cwp6ZXJvX2RhdGExWyw2OjU1XSA8LSByb3VuZCh6ZXJvX2RhdGExWyw2OjU1XSkKYGBgCgpHcmFwaHMgdG8gQ2hlY2sKYGBge3J9CiMgSW5kaXZpZHVhbCBTcGVjaWVzIFBsb3RzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUGl2b3QgdG8gbG9uZyBkYXRhCmNvdW50X2xvbmcgPC0gdGlkeXI6OnBpdm90X2xvbmdlcih6ZXJvX2RhdGExLCBjb2xzID0gc3RhcnRzX3dpdGgoInNwIiksIG5hbWVzX3RvID0gIlNwZWNpZXMiKQoKIyBQbG90IHRoZSBkYXRhCmNvdW50X2xvbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVGltZSwgeSA9IHZhbHVlLCBjb2xvdXIgPSBhcy5mYWN0b3IoSUQpLAogICAgICAgICAgICAgZ3JvdXAgPSBhcy5mYWN0b3IoSUQpLCBsaW5ldHlwZSA9IGFzLmZhY3RvcihJRCkpKSArCiAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21faml0dGVyKCkgKwogIHlsYWIoIkNvdW50IikgKwogIGxhYnMobGluZXR5cGUgPSAiSUQiLCBjb2xvciA9ICJJRCIpICsKICBmYWNldF93cmFwKH4gU3BlY2llcykgKyAgIyBDcmVhdGUgYSBwYW5lbCBmb3IgZWFjaCBzcGVjaWVzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZ2d0aXRsZSgiVGltZSBTZXJpZXMgb2YgTj01MCwgMHMiKQoKCiMgRGlzdHJpYnV0aW9uIG9mIGNvdW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpoaXN0KGFzLm1hdHJpeCh6ZXJvX2RhdGExWyw2OjU1XSksIGJyZWFrcyA9IDEwMCwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgR0xWIERhdGEiLCB4bGFiID0gIkNvdW50cyIpCgojIENvcnJlbGF0aW9uIG1hdHJpeApjb3JfcmF3MSA8LSBjb3IoKHplcm9fZGF0YTFbLDY6NTVdKSwgbWV0aG9kID0gInNwZWFybWFuIikKaGVhdG1hcChjb3JfcmF3MSwgQ29sdiA9IE5BLCBSb3d2ID0gTkEsIG1haW4gPSAiQ29ycmVsYXRpb24gb2YgMCBpbmZsYXRlZCBubyBjb3ZhcmlhdGVzIikKYGBgCgoKU2F2ZSB0aGUgQ291bnRzCmBgYHtyfQp3cml0ZS5jc3YobWV0YV9jb3VudHMsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfMS4wLmNzdiIpKQp3cml0ZS5jc3YoTG9uZ19kYXRhX25ldywgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl9Db3ZfMS4wLmNzdiIpKQp3cml0ZS5jc3YoemVyb19kYXRhMSwgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl9Db3ZaZXJvXzEuMC5jc3YiKSkKYGBgCgoKCiMgNS4gU2ltdWxhdGUgYmV0YSA9IDguMAoqKiogCgpfX1NpbXVsYXRlIENvdW50c19fICAKU2ltdWxhdGUgR0xWIGZvciA1MCBpbmRpdmlkdWFscywgNTAgc3BlY2llcywgMTAgdGltZXBvaW50cywgQ29ubmVjdGFuY2UgPSAwLjkwLCBTZXggQmV0YSA9IDguMApgYGB7cn0KIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKCiMgU3RlcCAxIFJ1biBHTFYgZm9yIG4gbnVtYmVyIG9mIHN1YmplY3QgYW5kIHRpbWVwb2ludHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBHZW5lcmF0ZSBpbnRlcmFjdGlvbnMgZnJvbSB1bmlmb3JtIGRpc3RyaWJ1dGlvbgpBX3VuaWZvcm0gPC0gcmFuZG9tQSgKICAgIG5fc3BlY2llcyA9IDUwLAogICAgZGlhZ29uYWwgPSAtMS4wLAogICAgY29ubmVjdGFuY2UgPSAwLjkwKQoKIyBDcmVhdGUgYW4gZW1wdHkgbGlzdCB0byBzdG9yZSB0aGUgY291bnQgdGFibGVzIGZvciBlYWNoIHN1YmplY3QKY291bnRfdGFibGVzIDwtIGxpc3QoKQoKCiMgTG9vcCB0aHJvdWdoIDUwIHN1YmplY3RzIGFuZCBnZW5lcmF0ZSBjb3VudCB0YWJsZXMgZm9yIGVhY2gKZm9yIChpIGluIDE6NTApIHsKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAjIEdlbmVyYWxpemVkIExvdGthLVZvbHRlcnJhIChnTFYpCiAgdHNlX2dsdiA8LSBzaW11bGF0ZUdMVihuX3NwZWNpZXMgPSA1MCwKICAgICAgICAgICAgICAgICAgICAgICBBID0gQV91bmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgIHRfc3RhcnQgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICB0X3N0b3JlID0gMTAsCiAgICAgICAgICAgICAgICAgICAgICAgc3RvY2hhc3RpYyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIG5vcm0gPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl92YXJpYW5jZSA9IDAuMDEpCiAgCiAgIyBHZXQgdGhlIGNvdW50IHRhYmxlCiAgc2ltX2RhdGEgPC0gdHNlX2dsdkBhc3NheXNAZGF0YUBsaXN0RGF0YVtbImNvdW50cyJdXQogIAogICMgU3RvcmUgdGhlIGNvdW50IHRhYmxlIGluIHRoZSBsaXN0CiAgY291bnRfdGFibGVzW1tpXV0gPC0gdChzaW1fZGF0YSkKfQoKIyBTdGVwIDIgLSBNZXJnZSB0b2dldGhlcgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgQ29tYmluZSBhbGwgY291bnQgdGFibGVzIGludG8gb25lIGRhdGEgZnJhbWUKY29tYmluZWRfY291bnRfdGFibGUgPC0gZG8uY2FsbChyYmluZCwgY291bnRfdGFibGVzKQoKIyBSZW5hbWUgdGhlIHJvd25hbWVzIGJhc2VkIG9uIHRoZSBjb3VudCB0YWJsZSBudW1iZXIKcm93bmFtZXMoY29tYmluZWRfY291bnRfdGFibGUpIDwtIHBhc3RlMCgiU2JqIiwgcmVwKDE6NTAsIGVhY2ggPSBucm93KGNvdW50X3RhYmxlc1tbMV1dKSksICJfVGltZSIsIDE6MTApCgpgYGAKCgpfX0NyZWF0ZSBGYWtlIE1ldGFkYXRhX18gIAoxLiBTZXggKE0gb3IgRiwgNTAvNTAgUmF0aW8pCjIuIEFnZSAtIHNhbXBsZSBmcm9tIGJldHdlZW4gMTggYW5kIDQ1CjMuIEJNSSAtIHNhbXBsZSBiZXR3ZWVuIDE4IGFuZCAzNQoKTWFrZSBNZXRhZGF0YSBhbmQgbWVyZ2Ugd2l0aCB0aGUgY291bnQgZGF0YQpgYGB7cn0KIyBEZiAxIGlzIE1ldGFkYXRhCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCm1ldGFfZGF0YSA8LSAgZXhwYW5kLmdyaWQoVGltZSA9IDE6MTAsSUQgPSAxOjUwKQpyb3duYW1lcyhtZXRhX2RhdGEpIDwtIHJvd25hbWVzKGNvbWJpbmVkX2NvdW50X3RhYmxlKQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQptZXRhX2RhdGEkU2V4IDwtIHJlcChjKDAsIDEpLCBlYWNoID0gNTApCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRBZ2UgPC0gcmVwKHNhbXBsZSgxODo0NSwgNTAsIHJlcGxhY2UgPSBUUlVFKSwgZWFjaCA9IDEwKQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQptZXRhX2RhdGEkQk1JIDwtIHJlcChzYW1wbGUoMTg6MzUsIDUwLCByZXBsYWNlID0gVFJVRSksIGVhY2ggPSAxMCkKCiMgQ2VudGVyIHRoZSBjb250aW51b3VzIHZhcmlhYmxlcwptZXRhX2RhdGEkQWdlIDwtIG1ldGFfZGF0YSRBZ2UgLSBtZWFuKG1ldGFfZGF0YSRBZ2UpCm1ldGFfZGF0YSRCTUkgPC0gbWV0YV9kYXRhJEJNSSAtIG1lYW4obWV0YV9kYXRhJEJNSSkKCgojIERmIDIgaXMgTWV0YWRhdGEgbWVyZ2VkIHdpdGggQ291bnRzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiNSb3VuZCBvZmYgYW5kIGluY3JlYXNlCmNvbWJpbmVkX2NvdW50X3RhYmxlIDwtIGFzLmRhdGEuZnJhbWUoY29tYmluZWRfY291bnRfdGFibGUgKyBhYnMobWluKGNvbWJpbmVkX2NvdW50X3RhYmxlKSkpCmNvbWJpbmVkX2NvdW50X3RhYmxlIDwtIChjb21iaW5lZF9jb3VudF90YWJsZSkqMTAKbWV0YV9jb3VudHMgPC0gYmFzZTo6bWVyZ2UobWV0YV9kYXRhLCBjb21iaW5lZF9jb3VudF90YWJsZSwgYnkgPSJyb3cubmFtZXMiLCBhbGwgPSBUUlVFKQptZXRhX2NvdW50cyA8LSBjb2x1bW5fdG9fcm93bmFtZXMobWV0YV9jb3VudHMsICJSb3cubmFtZXMiKQoKCmBgYAoKCkFkZCBpbiBiaW9sb2dpY2FsIGNvdmFyaWF0ZXMKYGBge3J9CiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCiMgQWRkaW4gY292YXJpYXRlcwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgU2V0IHVwIG5ldyBkYXRhZnJhbWUKTG9uZ19kYXRhX25ldyA8LSBtZXRhX2NvdW50cwoKCiMgTG9vcCBydW5uaW5nIHRoZSBMTSB0byBnZXQgbmV3IHZhcmlhYmxlcyB3aXRoIGVycm9yIHRoYXQgaGFzIGEgcmFuZ2Ugb2YgdmFsdWVzCgojIFRheGEgMjEgLSAzMCB3aWxsIGhhdmUgU2V4IGVmZmVjdApmb3IgKGkgaW4gMjY6MzUpIHsKICBlcnJvciA8LSBybm9ybShucm93KExvbmdfZGF0YV9uZXcpLCBtZWFuID0gMSwgc2QgPSAwLjYpCiAgTG9uZ19kYXRhX25ld1ssIGldIDwtIExvbmdfZGF0YV9uZXdbLCBpXSArIDguMCAqIExvbmdfZGF0YV9uZXckU2V4ICsgZXJyb3IKfQoKCiMgcm91bmQgdGhlIGNvdW50cyB0byBicmluZyB0aGVtIGJhY2sgdXAgdG8gMAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIEFkZCB0aGUgbWluaW11bSB2YWx1ZSB0byBicmluZyBldmVyeXRoaW5nIHVwIHRvIGF0IGxlYXN0IDAKY291bnRfdGFibGUxIDwtIExvbmdfZGF0YV9uZXdbLDY6NTVdCgoKIyBzY2FsZSB0byBwb3NpdGl2ZSBhbmQgbWFrZSBsYXJnZXIKY291bnRfdGFibGUxIDwtIGNvdW50X3RhYmxlMSArIGFicyhtaW4oY291bnRfdGFibGUxKSkKY291bnRfdGFibGUxIDwtIHJvdW5kKGNvdW50X3RhYmxlMSoxMCkKCiNjaGFuZ2UgTG9uZ19kYXRhX25ldwpMb25nX2RhdGFfbmV3Wyw2OjU1XSA8LSBjb3VudF90YWJsZTEKYGBgCgoKCk5vdyBBZGQgaW4gMHMKYGBge3J9CiMgU2V0IHVwIG5ldyBkYXRhZnJhbWUKcHJlZGF0YV8wIDwtIGNvdW50X3RhYmxlMQoKIyBBZGQgdGhlIDBzIGJhY2sgaW4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiMgU3RlcCAxOiBDYWxjdWxhdGUgdG90YWwgY291bnRzIGZvciBlYWNoIGNvbHVtbgp0b3RhbF9jb3VudHMgPC0gY29sU3VtcyhwcmVkYXRhXzApCgoKIyBTdGVwIDI6IENyZWF0ZSBwcm9iYWJpbGl0eSBncmFkaWVudApncmFkaWVudCA8LSBzZXEoMC41LCAwLjIsIGxlbmd0aC5vdXQgPSBuY29sKHByZWRhdGFfMCkpCgojIFN0ZXAgMzogTWFrZSB0aGUgcHJvYmFiaWxpdHkgZ3JhZGllbnQgaW52ZXJzZSB0byB0b3RhbCBjb3VudHMgKGllIGhpZ2hlciB0b3RhbCB2YWx1ZSwgbG93ZXIgcHJvcG9ydGlvbiBvZiAwcykKdG90YWxfY291bnRzIDwtIHRvdGFsX2NvdW50c1tvcmRlcih0b3RhbF9jb3VudHMpXQpncmFkaWVudCA8LSBncmFkaWVudFtvcmRlcigtZ3JhZGllbnQpXQoKIyBTdGVwIDQgJiA1OiBHZW5lcmF0ZSByYW5kb20gbnVtYmVycyBhbmQgc2V0IGNvdW50cyB0byAwIGJhc2VkIG9uIHByb2JhYmlsaXR5IGdyYWRpZW50Cgpmb3IgKGkgaW4gc2VxX2Fsb25nKHRvdGFsX2NvdW50cykpIHsKICBwcm9iIDwtIGdyYWRpZW50W2ldCiAgIyBDYWxjdWxhdGUgbnVtYmVyIG9mIDBzIHRvIGFkZCBiYXNlZCBvbiBwcm9iYWJpbGl0eQogIG51bV96ZXJvcyA8LSBzdW0ocnVuaWYobnJvdyhwcmVkYXRhXzApKSA8PSBwcm9iKQogICMgUmFuZG9tbHkgc2VsZWN0IHJvd3MgdG8gc2V0IHRvIDAKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAgcm93c190b196ZXJvIDwtIHNhbXBsZShucm93KHByZWRhdGFfMCksIG51bV96ZXJvcykKICAjIFNldCBjb3VudHMgdG8gMAogIHByZWRhdGFfMFtyb3dzX3RvX3plcm8sIGldIDwtIDAKfQoKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIGZvciBwbG90dGluZwp6ZXJvX2RhdGExIDwtIG1lcmdlKG1ldGFfZGF0YSwgcHJlZGF0YV8wLCBieSA9IDApCnplcm9fZGF0YTEgPC0gY29sdW1uX3RvX3Jvd25hbWVzKHplcm9fZGF0YTEsICJSb3cubmFtZXMiKQojcm91bmQgdGhlIGNvdW50cwp6ZXJvX2RhdGExWyw2OjU1XSA8LSByb3VuZCh6ZXJvX2RhdGExWyw2OjU1XSkKYGBgCgpHcmFwaHMgdG8gQ2hlY2sKYGBge3J9CiMgSW5kaXZpZHVhbCBTcGVjaWVzIFBsb3RzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUGl2b3QgdG8gbG9uZyBkYXRhCmNvdW50X2xvbmcgPC0gdGlkeXI6OnBpdm90X2xvbmdlcih6ZXJvX2RhdGExLCBjb2xzID0gc3RhcnRzX3dpdGgoInNwIiksIG5hbWVzX3RvID0gIlNwZWNpZXMiKQoKIyBQbG90IHRoZSBkYXRhCmNvdW50X2xvbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVGltZSwgeSA9IHZhbHVlLCBjb2xvdXIgPSBhcy5mYWN0b3IoSUQpLAogICAgICAgICAgICAgZ3JvdXAgPSBhcy5mYWN0b3IoSUQpLCBsaW5ldHlwZSA9IGFzLmZhY3RvcihJRCkpKSArCiAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21faml0dGVyKCkgKwogIHlsYWIoIkNvdW50IikgKwogIGxhYnMobGluZXR5cGUgPSAiSUQiLCBjb2xvciA9ICJJRCIpICsKICBmYWNldF93cmFwKH4gU3BlY2llcykgKyAgIyBDcmVhdGUgYSBwYW5lbCBmb3IgZWFjaCBzcGVjaWVzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZ2d0aXRsZSgiVGltZSBTZXJpZXMgb2YgTj01MCwgMHMiKQoKCiMgRGlzdHJpYnV0aW9uIG9mIGNvdW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpoaXN0KGFzLm1hdHJpeCh6ZXJvX2RhdGExWyw2OjU1XSksIGJyZWFrcyA9IDEwMCwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgR0xWIERhdGEiLCB4bGFiID0gIkNvdW50cyIpCgojIENvcnJlbGF0aW9uIG1hdHJpeApjb3JfcmF3MSA8LSBjb3IoKHplcm9fZGF0YTFbLDY6NTVdKSwgbWV0aG9kID0gInNwZWFybWFuIikKaGVhdG1hcChjb3JfcmF3MSwgQ29sdiA9IE5BLCBSb3d2ID0gTkEsIG1haW4gPSAiQ29ycmVsYXRpb24gb2YgMCBpbmZsYXRlZCBubyBjb3ZhcmlhdGVzIikKYGBgCgoKU2F2ZSB0aGUgQ291bnRzCmBgYHtyfQp3cml0ZS5jc3YobWV0YV9jb3VudHMsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfOC4wLmNzdiIpKQp3cml0ZS5jc3YoTG9uZ19kYXRhX25ldywgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl9Db3ZfOC4wLmNzdiIpKQp3cml0ZS5jc3YoemVyb19kYXRhMSwgaGVyZSgiRGF0YSIsIkdMVl9TaW1EYXRhIiwgIkRhdGFzZXRfNSIsIkdMVl9Db3ZaZXJvXzguMC5jc3YiKSkKYGBgCgoKCgojIDYuIFNpbXVsYXRlIGJldGEgPSAxNS4wCioqKiAKCl9fU2ltdWxhdGUgQ291bnRzX18gIApTaW11bGF0ZSBHTFYgZm9yIDUwIGluZGl2aWR1YWxzLCA1MCBzcGVjaWVzLCAxMCB0aW1lcG9pbnRzLCBDb25uZWN0YW5jZSA9IDAuOTAsIFNleCBCZXRhID0gMTUuMApgYGB7cn0KIyBTZXQgc2VlZApzZXQuc2VlZCgxMjM0NSkKCiMgU3RlcCAxIFJ1biBHTFYgZm9yIG4gbnVtYmVyIG9mIHN1YmplY3QgYW5kIHRpbWVwb2ludHMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBHZW5lcmF0ZSBpbnRlcmFjdGlvbnMgZnJvbSB1bmlmb3JtIGRpc3RyaWJ1dGlvbgpBX3VuaWZvcm0gPC0gcmFuZG9tQSgKICAgIG5fc3BlY2llcyA9IDUwLAogICAgZGlhZ29uYWwgPSAtMS4wLAogICAgY29ubmVjdGFuY2UgPSAwLjkwKQoKIyBDcmVhdGUgYW4gZW1wdHkgbGlzdCB0byBzdG9yZSB0aGUgY291bnQgdGFibGVzIGZvciBlYWNoIHN1YmplY3QKY291bnRfdGFibGVzIDwtIGxpc3QoKQoKCiMgTG9vcCB0aHJvdWdoIDUwIHN1YmplY3RzIGFuZCBnZW5lcmF0ZSBjb3VudCB0YWJsZXMgZm9yIGVhY2gKZm9yIChpIGluIDE6NTApIHsKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAjIEdlbmVyYWxpemVkIExvdGthLVZvbHRlcnJhIChnTFYpCiAgdHNlX2dsdiA8LSBzaW11bGF0ZUdMVihuX3NwZWNpZXMgPSA1MCwKICAgICAgICAgICAgICAgICAgICAgICBBID0gQV91bmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgIHRfc3RhcnQgPSAwLCAKICAgICAgICAgICAgICAgICAgICAgICB0X3N0b3JlID0gMTAsCiAgICAgICAgICAgICAgICAgICAgICAgc3RvY2hhc3RpYyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIG5vcm0gPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl92YXJpYW5jZSA9IDAuMDEpCiAgCiAgIyBHZXQgdGhlIGNvdW50IHRhYmxlCiAgc2ltX2RhdGEgPC0gdHNlX2dsdkBhc3NheXNAZGF0YUBsaXN0RGF0YVtbImNvdW50cyJdXQogIAogICMgU3RvcmUgdGhlIGNvdW50IHRhYmxlIGluIHRoZSBsaXN0CiAgY291bnRfdGFibGVzW1tpXV0gPC0gdChzaW1fZGF0YSkKfQoKIyBTdGVwIDIgLSBNZXJnZSB0b2dldGhlcgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgQ29tYmluZSBhbGwgY291bnQgdGFibGVzIGludG8gb25lIGRhdGEgZnJhbWUKY29tYmluZWRfY291bnRfdGFibGUgPC0gZG8uY2FsbChyYmluZCwgY291bnRfdGFibGVzKQoKIyBSZW5hbWUgdGhlIHJvd25hbWVzIGJhc2VkIG9uIHRoZSBjb3VudCB0YWJsZSBudW1iZXIKcm93bmFtZXMoY29tYmluZWRfY291bnRfdGFibGUpIDwtIHBhc3RlMCgiU2JqIiwgcmVwKDE6NTAsIGVhY2ggPSBucm93KGNvdW50X3RhYmxlc1tbMV1dKSksICJfVGltZSIsIDE6MTApCgpgYGAKCgpfX0NyZWF0ZSBGYWtlIE1ldGFkYXRhX18gIAoxLiBTZXggKE0gb3IgRiwgNTAvNTAgUmF0aW8pCjIuIEFnZSAtIHNhbXBsZSBmcm9tIGJldHdlZW4gMTggYW5kIDQ1CjMuIEJNSSAtIHNhbXBsZSBiZXR3ZWVuIDE4IGFuZCAzNQoKTWFrZSBNZXRhZGF0YSBhbmQgbWVyZ2Ugd2l0aCB0aGUgY291bnQgZGF0YQpgYGB7cn0KIyBEZiAxIGlzIE1ldGFkYXRhCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCm1ldGFfZGF0YSA8LSAgZXhwYW5kLmdyaWQoVGltZSA9IDE6MTAsSUQgPSAxOjUwKQpyb3duYW1lcyhtZXRhX2RhdGEpIDwtIHJvd25hbWVzKGNvbWJpbmVkX2NvdW50X3RhYmxlKQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQptZXRhX2RhdGEkU2V4IDwtIHJlcChjKDAsIDEpLCBlYWNoID0gNTApCiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCm1ldGFfZGF0YSRBZ2UgPC0gcmVwKHNhbXBsZSgxODo0NSwgNTAsIHJlcGxhY2UgPSBUUlVFKSwgZWFjaCA9IDEwKQojIFNldCBzZWVkCnNldC5zZWVkKDEyMzQ1KQptZXRhX2RhdGEkQk1JIDwtIHJlcChzYW1wbGUoMTg6MzUsIDUwLCByZXBsYWNlID0gVFJVRSksIGVhY2ggPSAxMCkKCiMgQ2VudGVyIHRoZSBjb250aW51b3VzIHZhcmlhYmxlcwptZXRhX2RhdGEkQWdlIDwtIG1ldGFfZGF0YSRBZ2UgLSBtZWFuKG1ldGFfZGF0YSRBZ2UpCm1ldGFfZGF0YSRCTUkgPC0gbWV0YV9kYXRhJEJNSSAtIG1lYW4obWV0YV9kYXRhJEJNSSkKCgojIERmIDIgaXMgTWV0YWRhdGEgbWVyZ2VkIHdpdGggQ291bnRzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiNSb3VuZCBvZmYgYW5kIGluY3JlYXNlCmNvbWJpbmVkX2NvdW50X3RhYmxlIDwtIGFzLmRhdGEuZnJhbWUoY29tYmluZWRfY291bnRfdGFibGUgKyBhYnMobWluKGNvbWJpbmVkX2NvdW50X3RhYmxlKSkpCmNvbWJpbmVkX2NvdW50X3RhYmxlIDwtIChjb21iaW5lZF9jb3VudF90YWJsZSkqMTAKbWV0YV9jb3VudHMgPC0gYmFzZTo6bWVyZ2UobWV0YV9kYXRhLCBjb21iaW5lZF9jb3VudF90YWJsZSwgYnkgPSJyb3cubmFtZXMiLCBhbGwgPSBUUlVFKQptZXRhX2NvdW50cyA8LSBjb2x1bW5fdG9fcm93bmFtZXMobWV0YV9jb3VudHMsICJSb3cubmFtZXMiKQoKCmBgYAoKCkFkZCBpbiBiaW9sb2dpY2FsIGNvdmFyaWF0ZXMKYGBge3J9CiMgU2V0IHNlZWQKc2V0LnNlZWQoMTIzNDUpCiMgQWRkaW4gY292YXJpYXRlcwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgU2V0IHVwIG5ldyBkYXRhZnJhbWUKTG9uZ19kYXRhX25ldyA8LSBtZXRhX2NvdW50cwoKCiMgTG9vcCBydW5uaW5nIHRoZSBMTSB0byBnZXQgbmV3IHZhcmlhYmxlcyB3aXRoIGVycm9yIHRoYXQgaGFzIGEgcmFuZ2Ugb2YgdmFsdWVzCiMgVGF4YSAyMSAtIDMwIHdpbGwgaGF2ZSBTZXggZWZmZWN0CmZvciAoaSBpbiAyNjozNSkgewogIGVycm9yIDwtIHJub3JtKG5yb3coTG9uZ19kYXRhX25ldyksIG1lYW4gPSAxLCBzZCA9IDAuNikKICBMb25nX2RhdGFfbmV3WywgaV0gPC0gTG9uZ19kYXRhX25ld1ssIGldICsgMTUgKiBMb25nX2RhdGFfbmV3JFNleCArIGVycm9yCn0KCiMgcm91bmQgdGhlIGNvdW50cyB0byBicmluZyB0aGVtIGJhY2sgdXAgdG8gMAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIEFkZCB0aGUgbWluaW11bSB2YWx1ZSB0byBicmluZyBldmVyeXRoaW5nIHVwIHRvIGF0IGxlYXN0IDAKY291bnRfdGFibGUxIDwtIExvbmdfZGF0YV9uZXdbLDY6NTVdCgoKIyBzY2FsZSB0byBwb3NpdGl2ZSBhbmQgbWFrZSBsYXJnZXIKY291bnRfdGFibGUxIDwtIGNvdW50X3RhYmxlMSArIGFicyhtaW4oY291bnRfdGFibGUxKSkKY291bnRfdGFibGUxIDwtIHJvdW5kKGNvdW50X3RhYmxlMSoxMCkKCiNjaGFuZ2UgTG9uZ19kYXRhX25ldwpMb25nX2RhdGFfbmV3Wyw2OjU1XSA8LSBjb3VudF90YWJsZTEKYGBgCgoKCk5vdyBBZGQgaW4gMHMKYGBge3J9CiMgU2V0IHVwIG5ldyBkYXRhZnJhbWUKcHJlZGF0YV8wIDwtIGNvdW50X3RhYmxlMQoKIyBBZGQgdGhlIDBzIGJhY2sgaW4KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKCiMgU3RlcCAxOiBDYWxjdWxhdGUgdG90YWwgY291bnRzIGZvciBlYWNoIGNvbHVtbgp0b3RhbF9jb3VudHMgPC0gY29sU3VtcyhwcmVkYXRhXzApCgoKIyBTdGVwIDI6IENyZWF0ZSBwcm9iYWJpbGl0eSBncmFkaWVudApncmFkaWVudCA8LSBzZXEoMC41LCAwLjIsIGxlbmd0aC5vdXQgPSBuY29sKHByZWRhdGFfMCkpCgojIFN0ZXAgMzogTWFrZSB0aGUgcHJvYmFiaWxpdHkgZ3JhZGllbnQgaW52ZXJzZSB0byB0b3RhbCBjb3VudHMgKGllIGhpZ2hlciB0b3RhbCB2YWx1ZSwgbG93ZXIgcHJvcG9ydGlvbiBvZiAwcykKdG90YWxfY291bnRzIDwtIHRvdGFsX2NvdW50c1tvcmRlcih0b3RhbF9jb3VudHMpXQpncmFkaWVudCA8LSBncmFkaWVudFtvcmRlcigtZ3JhZGllbnQpXQoKIyBTdGVwIDQgJiA1OiBHZW5lcmF0ZSByYW5kb20gbnVtYmVycyBhbmQgc2V0IGNvdW50cyB0byAwIGJhc2VkIG9uIHByb2JhYmlsaXR5IGdyYWRpZW50Cgpmb3IgKGkgaW4gc2VxX2Fsb25nKHRvdGFsX2NvdW50cykpIHsKICBwcm9iIDwtIGdyYWRpZW50W2ldCiAgIyBDYWxjdWxhdGUgbnVtYmVyIG9mIDBzIHRvIGFkZCBiYXNlZCBvbiBwcm9iYWJpbGl0eQogIG51bV96ZXJvcyA8LSBzdW0ocnVuaWYobnJvdyhwcmVkYXRhXzApKSA8PSBwcm9iKQogICMgUmFuZG9tbHkgc2VsZWN0IHJvd3MgdG8gc2V0IHRvIDAKICAjIFNldCB0aGUgc2VlZCBmb3IgZWFjaCBzdWJqZWN0CiAgc2V0LnNlZWQoMTIzNDUgKyBpKSAgCiAgcm93c190b196ZXJvIDwtIHNhbXBsZShucm93KHByZWRhdGFfMCksIG51bV96ZXJvcykKICAjIFNldCBjb3VudHMgdG8gMAogIHByZWRhdGFfMFtyb3dzX3RvX3plcm8sIGldIDwtIDAKfQoKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIGZvciBwbG90dGluZwp6ZXJvX2RhdGExIDwtIG1lcmdlKG1ldGFfZGF0YSwgcHJlZGF0YV8wLCBieSA9IDApCnplcm9fZGF0YTEgPC0gY29sdW1uX3RvX3Jvd25hbWVzKHplcm9fZGF0YTEsICJSb3cubmFtZXMiKQojcm91bmQgdGhlIGNvdW50cwp6ZXJvX2RhdGExWyw2OjU1XSA8LSByb3VuZCh6ZXJvX2RhdGExWyw2OjU1XSkKYGBgCgpHcmFwaHMgdG8gQ2hlY2sKYGBge3J9CiMgSW5kaXZpZHVhbCBTcGVjaWVzIFBsb3RzCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgUGl2b3QgdG8gbG9uZyBkYXRhCmNvdW50X2xvbmcgPC0gdGlkeXI6OnBpdm90X2xvbmdlcih6ZXJvX2RhdGExLCBjb2xzID0gc3RhcnRzX3dpdGgoInNwIiksIG5hbWVzX3RvID0gIlNwZWNpZXMiKQoKIyBQbG90IHRoZSBkYXRhCmNvdW50X2xvbmcgJT4lCiAgZ2dwbG90KGFlcyh4ID0gVGltZSwgeSA9IHZhbHVlLCBjb2xvdXIgPSBhcy5mYWN0b3IoSUQpLAogICAgICAgICAgICAgZ3JvdXAgPSBhcy5mYWN0b3IoSUQpLCBsaW5ldHlwZSA9IGFzLmZhY3RvcihJRCkpKSArCiAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21faml0dGVyKCkgKwogIHlsYWIoIkNvdW50IikgKwogIGxhYnMobGluZXR5cGUgPSAiSUQiLCBjb2xvciA9ICJJRCIpICsKICBmYWNldF93cmFwKH4gU3BlY2llcykgKyAgIyBDcmVhdGUgYSBwYW5lbCBmb3IgZWFjaCBzcGVjaWVzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZ2d0aXRsZSgiVGltZSBTZXJpZXMgb2YgTj01MCwgMHMiKQoKCiMgRGlzdHJpYnV0aW9uIG9mIGNvdW50cwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpoaXN0KGFzLm1hdHJpeCh6ZXJvX2RhdGExWyw2OjU1XSksIGJyZWFrcyA9IDEwMCwgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgR0xWIERhdGEiLCB4bGFiID0gIkNvdW50cyIpCgojIENvcnJlbGF0aW9uIG1hdHJpeApjb3JfcmF3MSA8LSBjb3IoKHplcm9fZGF0YTFbLDY6NTVdKSwgbWV0aG9kID0gInNwZWFybWFuIikKaGVhdG1hcChjb3JfcmF3MSwgQ29sdiA9IE5BLCBSb3d2ID0gTkEsIG1haW4gPSAiQ29ycmVsYXRpb24gb2YgMCBpbmZsYXRlZCBubyBjb3ZhcmlhdGVzIikKYGBgCgoKU2F2ZSB0aGUgQ291bnRzCmBgYHtyfQp3cml0ZS5jc3YobWV0YV9jb3VudHMsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfMTUuMC5jc3YiKSkKd3JpdGUuY3N2KExvbmdfZGF0YV9uZXcsIGhlcmUoIkRhdGEiLCJHTFZfU2ltRGF0YSIsICJEYXRhc2V0XzUiLCJHTFZfQ292XzE1LjAuY3N2IikpCndyaXRlLmNzdih6ZXJvX2RhdGExLCBoZXJlKCJEYXRhIiwiR0xWX1NpbURhdGEiLCAiRGF0YXNldF81IiwiR0xWX0Nvdlplcm9fMTUuMC5jc3YiKSkKYGBgCg==